Skip to main content
fbarbozac
Associate
March 19, 2020
Solved

Overflow on timeouts in STM32 HAL driver

  • March 19, 2020
  • 4 replies
  • 2822 views

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;
 }
 }
...

This topic has been closed for replies.
Best answer by KnarfB

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

4 replies

KnarfB
KnarfBBest answer
Super User
March 19, 2020

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

fbarbozac
fbarbozacAuthor
Associate
March 19, 2020

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.

waclawek.jan
Super User
March 19, 2020

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

Shorter types need explicit modulo.

JW

Piranha
Principal III
March 19, 2020

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.