Clock Gating (I2C HSI kernel clock) prevents Standby
Hi,
I have a situation which I would like to understand better:
I have an STM32U595ZJT6Q with I2C2 configured to use HSI16 (not PCLK1) as its kernel clock. I put the STM32 into Standby to save power.
Recently I implemented Clock Gating to save power when not in Standby.
I call
__HAL_RCC_I2C2_CLK_DISABLE();
...to gate/pause the I2C kernel clock when I'm not using it.
I call:
__HAL_RCC_I2C2_CLK_ENABLE();
...to un-gate/resume the I2C kernel clock when I wish to use it.
This seems to work fine and I do save a significant amount of power.
However! When I attempt to put the STM32 into Standby, something that previously worked fine, the MCU does NOT drop to Standby power level and the ST-Link debugger disconnects. The latter happens even when I have called:
HAL_DBGMCU_EnableDBGStandbyMode();
This leads me to believe that the MCU has entered some kind of unpleasant hardfault state, but without actually calling any fault handlers. I don't think (unless I am checking it wrong) the NVIC has any pending interrupts that would prevent Standby.
I can avoid this occurrence by either:
- Not clock gating
- Using PCLK1, instead of the HSI16, as my I2C2 kernel clock
I have two questions:
- What do we think happened to my STM32 when I attempted to go to Standby?
Having it enter an undefined state without apparent warning (eg. without calling a handler) is a bit concerning when I'm trying to build something that must go to Standby reliably.
How do I debug/diagnose this behaviour? - What is going on with I2C2 to apparently cause such behaviour?
Am I doing Clock Gating wrong? Am I meant to wait for some bit to set/unset before disabling the kernel clock?
In essence, how do I arm myself with the tools to prevent his happening again with other peripherals? I would also like the flexibility to use other clock sources as kernel clocks and implement clock gating without fear of Standby not working.
Notes:
This issue occurs only if I2C2 is clock gated (disabled) when I attempt to go to Standby. Re-enabling the clock just before going to Standby appears to fix the issue make the issue go away.
It feels like a race hazard is occurring. If I insert nops before the call to gate/disable the clock, the issue appears to resolve itself. So I can imagine that I'm gating the clock whilst the peripheral is in the middle of a register update. If so, that begs the questions: How do I detect this (ie do I need to wait on a bit before gating the clock)? And why does that cause the MCU the silently refuse to go to Standby?
