2021-06-29 2:43 AM
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?
2025-07-27 7:56 AM
> 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.
2025-07-27 8:50 AM
> 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.
2025-07-27 10:00 AM
> 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.
2025-07-27 10:29 AM
> ICSR: 0x00400000
So ISRPENDING=1, but VECTPENDING=0, which suggests an interrupt will soon fire but the core hasn't been told which one yet.
I also notice that line 7554 in your code doesn't match the github repo. Not sure if this is significant or not. Your line number is 5 off from the expected.
2025-07-27 10:36 AM
This type of trouble require hw debug ok is toggle led or SWV. How is your timeout value used in call HAL_I2C_Mem_Read ? Check you code return value?
2025-07-27 12:11 PM
> This type of trouble require hw debug ok is toggle led or SWV. How is your timeout value used in call HAL_I2C_Mem_Read ? Check you code return value?
I added code to toggle the LED in SysTick_Handler, and it turns out that the ticks are updating after all. Also, following your suggestion I checked the timeout return value and it was not handled correctly. Thank you very much that fixes the issue for me.
> I also notice that line 7554 in your code doesn't match the github repo. Not sure if this is significant or not. Your line number is 5 off from the expected.
@TDK That was just the tick saving/checking code that I added. I diff'd the two drivers and they're the same otherwise. Also, you were right, it was indeed a problem in our driver. Thank you very much for trying to help and I'm very sorry for your trouble.