Skip to main content
TCarm.1
Associate
June 29, 2021
Question

Troubles with HAL_GetTick() in the I2C_WaitOnFlagUntilTimeout functions on a STM32G473 MCU

  • June 29, 2021
  • 7 replies
  • 3255 views

I am currently using the v1.6.1 of STM32CubeIDE and a STM32G473 MCU.

I have implemented an I2C bus and have noticed a major bug with the I2C_WaitOnFlagUntilTimeout functions. There is this condition:

if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U))

which is supposed to guarantee that the program doesn't get stuck into the while loop above (while (__HAL_I2C_GET_FLAG(hi2c, Flag) == Status)), but the tick value stop incrementing as soon as the program enters the function for a reason I don't understand. I have tried to increase the preempt priority of System tick timer (by lowering the value) but it didn't change a thing.

Does anyone know how to fix that?

7 replies

TDK
Super User
June 29, 2021

The only reason the ticks would stop increasing is if you're the same or higher priority interrupt, or if interrupts are disabled, or if SysTick is disabled.

"If you feel a post has answered your question, please click ""Accept as Solution""."
TCarm.1
TCarm.1Author
Associate
June 29, 2021

The thing is I don't even use the I2C bus in interrupt mode. I have no trouble when I don't call the HAL_I2C_Master_Transmit or HAL_I2C_Master_Receive functions, but as soon as I call them I got stuck into an infinite loop in I2C_WaitOnFlagUntilTimeout.

I have tried to low the priority interrupt, without effect, and I didn't disabled SysTick (the HAL_InitTick function returns HAL_OK)

TDK
Super User
June 29, 2021
Not sure. I see no reason why calling HAL_I2C_* function would cause the systick to stop functioning. Make sure you don't call it with HAL_MAX_DELAY if you want a timeout.
"If you feel a post has answered your question, please click ""Accept as Solution""."
Eich
Associate III
January 31, 2022

Could you find a soulution?

I have exactly the same problem. Systick stops and I2C remains in an endless loop waiting that the timeout is reached. That will never happen because Systick is no longer updated.

SCrum.1
Associate II
December 6, 2022

I also have this exact same problem. STM32G0B0. Somewhere in the HAL_I2C_Master_Transmit function, the tick timer interrupt stops firing. In my case HAL_I2C_Master_Transmit returns an error because the I2C device does not acknowledge. So I try and do a short delay and try again, but its stuck in HAL_Delay as the tick value is no longer updating.

Associate II
July 31, 2024

@TCarm.1 @SCrum.1 @Eich @TDK  Does anyone have a solution to this problem i am facing the same problem with stm32l5 board and i cannot get a way out of it if anyone of you has found the solution do let me know

 

Reagrds

Neev

TDK
Super User
July 31, 2024

If HAL_GetTick fails to increment, it's generally due to it having lower priority than the thread you're calling it from. There are many posts on this.

If that is not it, post a new topic with sufficient information about the problem.

If you're sure the chip is configured correctly, prove it via screenshots. Likely there is something missing. These chips do what you tell them to do. If something isn't working, there's a reason.

"If you feel a post has answered your question, please click ""Accept as Solution""."
Ibrahim Abdalkader
Associate II
July 27, 2025

I'm having the exact same problem on both H7 and N6.

The issue boils down to this: the I2C driver logic is entirely dependent on timeouts to break out of loops if the bus gets into a bad state. However, when the bus is in such a state, the SysTick timer stops firing for reasons unknown. And no, it is not a priority issue, the SysTick IRQ is set to 0, and I am not even using I2C IRQs.

 

Did we miss something in the RM that explains this behavior? Will ST ever look into this issue?

TDK
Super User
July 27, 2025

Post a minimal working example.

Blaming ST for bugs in your code will not fix the problem.

"If you feel a post has answered your question, please click ""Accept as Solution""."
Ibrahim Abdalkader
Associate II
July 27, 2025

> Post a minimal working example.

There has to be a bus error to reproduce this bug. How do you propose I post a minimal example that reproduces that exactly? FWIW, the drivers gets stuck between I2C_WaitOnFlagUntilTimeout and I2C_IsErrorOccurred, on call to HAL_I2C_Mem_Read.

 

> Blaming ST for bugs in your code will not fix the problem.

Obviously, I'm not the only one with this exact same problem, so it may warrant a little bit more than just brushing it off as a 'problem in my code'. Also, it's not like the HAL is bug free.

TDK
Super User
July 27, 2025

> How do you propose I post a minimal example that reproduces that exactly?

If the problem is a bus error, one way would be to use a GPIO pin to give a defined bus state. What bus error is occurring?

 

SysTick is entirely independent from the I2C peripheral. It's part of the cortex core. The mechanics of SysTick randomly stopping within an I2C routine just doesn't check out.

Likely if you posted your code in full there is an issue that could be resolved. Otherwise, it's a wild goose chase to show that HAL is not at fault on code that isn't even shown, would you agree? Other than providing working examples on a variety of boards, what exactly are you looking for from ST?

 

Trying to approach the problem more objectively with the internal question "why isn't this working?" rather than "someone else is at fault" might be more productive. Maybe HAL is at fault, but in that case you should be able to show exactly what isn't working. Processor states can be shown, interrupt configuration, priorities, etc.

"If you feel a post has answered your question, please click ""Accept as Solution""."
Ibrahim Abdalkader
Associate II
July 27, 2025

> If the problem is a bus error, one way would be to use a GPIO pin to give a defined bus state. What bus error is occurring?

 

I'm not exactly sure. The slave device misbehaves or become non-responsive if accessed too soon after power-on. When that happens, the driver gets stuck in an infinite loop. If I try to single-step through I2C_IsErrorOccurred, one of a few things happens: it somehow magically gets itself unstuck and the rest of the code proceeds normally, or it sets HAL_I2C_ERROR_AF, indicating a timeout, or it sets HAL_I2C_ERROR_BERR, indicating a bus error.

I suspect this behavior might be affected by compiler optimizations. I’ve noticed that some volatile registers are being cached in local variables, which could explain why it doesn't get stuck when single stepped.

 

> SysTick is entirely independent from the I2C peripheral. It's part of the cortex core. The mechanics of SysTick randomly stopping within an I2C routine just doesn't check out.

 

I understand that, and I don't see what I2C has to do with SysTick, however it is what I’m observing. On entry to HAL_I2C_Mem_Read, I save the current tick count in tick_start. I wait a minute or two then attach the debugger and break. I find it stuck in either  I2C_WaitOnFlagUntilTimeout or I2C_IsErrorOccurred with tick_start==uwTick:

I2C_IsErrorOccurred (hi2c=hi2c@entry=0x340030b4 <I2CHandle3>, Timeout=Timeout@entry=1000, 
 Tickstart=Tickstart@entry=3557) at lib/stm32/n6/src/stm32n6xx_hal_i2c.c:7554
7554	 if (HAL_IS_BIT_SET(itflag, I2C_FLAG_BERR))
(gdb) print tick_start
$25 = 3557
(gdb) print uwTick
$26 = 3557


Note that while in this state:

1) IRQs are enabled, no priority masking:

PRIMASK: 0x00000000 - IRQs ENABLED
FAULTMASK: 0x00000000 - Fault exceptions ENABLED
BASEPRI: 0x00000000 - No priority masking

2) CPU is not executing an exception:

ICSR: 0x00400000 (VectActive: 0, VectPending: 0, RetToBase: 0, PendSV: 0, SysTick: 0)

3) SysTick is Not masked:

(gdb) print /x SysTick->CTRL
$5 = 0x7

 

> but in that case you should be able to show exactly what isn't working. Processor states can be shown, interrupt configuration, priorities, etc.


FWIW other common registers, which seem fine to me:

CPUID: 0x411fd221 (Implementer: 0x41, Variant: 0x1, Architecture: 0xf, PartNo: 0xd22, Revision: 0x1)
ICSR: 0x00400000 (VectActive: 0, VectPending: 0, RetToBase: 0, PendSV: 0, SysTick: 0)
VTOR: 0x70080000
AIRCR: 0xfa050300 (VectKey: 0xfa05, PriGroup: 3, Endian: 0)
SCR: 0x00000000 (SevOnPend: 0, SleepDeep: 0, SleepOnExit: 0)
CCR: 0x00030201 (StkAlign: 1, BfhfnmIgn: 0, Div0Trp: 0, UnalignTrp: 0)
SHCSR: 0x00010000 (UsageFault: 0, BusFault: 0, MemManage: 1, SVCall: 0, SysTick: 0)
CFSR: 0x00000000 (UFSR: 0x0000, BFSR: 0x00, MMFSR: 0x00)
HFSR: 0x00000000 (DebugEvt: 0, Forced: 0, VectTbl: 0)
DFSR: 0x00000001 (External: 0, VCatch: 0, DWTTrap: 0, BkPt: 0, Halted: 1)
MMFAR: 0xd489762c (INVALID)
BFAR: 0xd489762c (INVALID)
AFSR: 0x00000000 (Implementation defined)
SHPR1: 0x00000000 (UsageFault: 0, BusFault: 0, MemManage: 0)
SHPR2: 0x00000000 (SVCall: 0)
SHPR3: 0x00f00000 (SysTick: 0, PendSV: 240)

 

> Other than providing working examples on a variety of boards, what exactly are you looking for from ST?

> Trying to approach the problem more objectively with the internal question "why isn't this working?" rather than "someone else is at fault" might be more productive

 

What I’m looking for is insight into what could possibly cause SysTick to stop firing when I2C is in that state as described above. I’d also appreciate it if someone could try to reproduce the issue, as it should be easy to do so if one can figure out how to mimic a misbehaving device somehow. In the meantime, I’ll see if we can reproduce it ourselves with a minimal example.