cancel
Showing results for 
Search instead for 
Did you mean: 

Overflow on timeouts in STM32 HAL driver

fbarbozac
Associate

Every code in HAL driver has the below structure that doesn´t care about overflow on HAL_GetTick().

...
      tickstart = HAL_GetTick();
 
      while (Something())
      {
        if (Timeout != HAL_MAX_DELAY)
        {
          if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
          {
            DoAnything();
            return HAL_ERROR;
          }
        }
...

I believe it can face some issues when the tick counter is about to overflow when the HAL is called and the results will be unpredictable.

Does anyone face this kind of problem?

One option to check the elapsed time is below:

uint32_t HAL_GetElapsedTimer(uint32_t u32_Time)
{
	uint32_t u32_Tick = HAL_GetTick();
 
	uint32_t u32_ElapsedTimer = ((u32_Time > u32_Tick) ?
								(uint32_t) (((uint64_t) u32_Tick + (1ULL<<32)) - u32_Time) :
								(uint32_t) (u32_Tick - u32_Time));
 
	return u32_ElapsedTimer;
}

And final HAL code:

...
      tickstart = HAL_GetTick();
 
      while (Something())
      {
        if (Timeout != HAL_MAX_DELAY)
        {
          if ((HAL_GetElapsedTimer(tickstart) > Timeout) || (Timeout == 0U))
          {
            DoAnything();
            return HAL_ERROR;
          }
        }
...

1 ACCEPTED SOLUTION

Accepted Solutions
KnarfB
Principal III
4 REPLIES 4
KnarfB
Principal III

Overflow in difference of unsigned values needs no special handling in C. See https://stackoverflow.com/questions/7221409/is-unsigned-integer-subtraction-defined-behavior

... if variables in the expression in question after usual arithmetic conversion are of unsigned int type.

Shorter types need explicit modulo.

JW

I wasn´t aware of this automatic modulo 2 in this kind of operation.

Great to know and thank you to let me learn this today.

Take care. COVID-19 is out there.

Piranha
Chief II

Shorter unsigned types work like this:

uint8_t tFinish = 1, tStart = UINT8_MAX, tPeriod = 2;
bool fExpired;
 
if ((uint8_t)(tFinish - tStart) >= tPeriod) {
	fExpired = true;
} else {
	fExpired = false;
}

Try changing tPeriod to 3 and see how it returns false. Variables are promoted to signed int type and the result of subtraction produces 1 - 255 = -254 with a type of signed int. Casting it to uint8_t will add to it UINT8_MAX+1 and produce the value 2,

https://stackoverflow.com/questions/50605/signed-to-unsigned-conversion-in-c-is-it-always-safe

This principle works correctly on overflows with all unsigned integer types, including the "smaller than int" ones - uint8_t and uint16_t.