Clocks reset to start-up config after exiting STOP mode #stm32 #pm


Marijn Stam <marijnstam@...>
 

Hello,

 

I'm using the Zephyr RTOS on a STM32F091 and have recently started working on implementing some low-power states (sleep and STOP). The system is fed by the PLL (48MHz) which is in turn fed by a HSE (20MHz).

I'm using the RTC peripheral to manage wake-ups, I simply set ALARMA at ~500ms before going to sleep.

 

What I see after waking up from STOP mode, is a bunch of garbage characters on the UART output and the whole system seemed to have slowed down significantly. A blinking LED for example, is now blinking much slower.

 

This is the code I use to enter the STOP mode (in functions pm_power_state_set and pm_power_state_exit_post_ops):

Note that this is not a Zephyr power driver, since the F091 was not supported yet. It is, however, heavily influenced by the other available power driver for STM32 platform (G0/L0 for example)

  1. //Switch to HSI clock before entering stop mode, needed so we can turn HSE off before entering (page 87 of RM)
  2. /* Enable HSI if not enabled */
  3. if (LL_RCC_HSI_IsReady() != 1) {
  4. /* Enable HSI */
  5. LL_RCC_HSI_Enable();
  6. while (LL_RCC_HSI_IsReady() != 1) {
  7. /* Wait for HSI ready */
  8. }
  9. }
  10.  
  11. /* Set HSI as SYSCLCK source */
  12. LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSI);
  13. while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSI) {
  14. }
  15. //Disable the HSE now that the HSI is enabled
  16. LL_RCC_HSE_Disable();
  17.  
  18. LL_RCC_PLL_Disable();
  19.  
  20. LL_PWR_SetPowerMode(LL_PWR_MODE_STOP_MAINREGU);
  21. LL_LPM_EnableDeepSleep();
  22.  
  23. //Disable SysTick interrupts so we don't immediately wake up
  24. LL_SYSTICK_DisableIT();
  25.  
  26. //This calls __WFI();
  27. k_cpu_idle();

Then this is called whenever the STOP mode is exited:

  1. LL_LPM_DisableSleepOnExit();
  2.  
  3. //Restore clock configuration
  4. stm32_clock_control_init(NULL);
  5.  
  6. //Re-enable the systick interrupt
  7. LL_SYSTICK_EnableIT();
  8.  
  9. irq_unlock(0);

The stm32_clock_control_init(NULL) does the following in sequence:

  • Configure some init struct for peripheral clock configuration
  • Enable default clocks (only SYSCFG peripheral clock in this case)
  • Clock is switched to HSI
  • PLL is disabled
  • Configure and switch to PLL with HSE as source clock
  • Disable HSI and MSI

To verify, I routed the SYSCLK to MCO, so I can monitor it on a scope. It shows the correct clock speed of 48MHz before entering the low-power procedure, then it is 8MHz after exiting STOP mode (HSI is startup clock).

After the stm32_clock_control_init(NULL) function has been executed, the SYSCLK is back at 48MHz, and the RCC registers show the right configuration.

Then, very shortly after, the RCC configuration is reset back to exit STOP conditions, i.e. HSI on, HSE and PLL off, HSI as system clock, back at 8MHz. This seems to happen asynchronously and I can't pinpoint why it happens.

This does not happen when I enter/exit sleep mode, only STOP.

I've verified that the Clock Security System is off. 

Any help with this would be greatly appreciated, as I am grasping at straws at this point.

 

Thank you kindly,

 

Marijn Stam

 

 

Join users@lists.zephyrproject.org to automatically receive all group messages.