zephyrproject-rtos / zephyr

Primary Git Repository for the Zephyr Project. Zephyr is a new generation, scalable, optimized, secure RTOS for multiple hardware architectures.
https://docs.zephyrproject.org
Apache License 2.0
10.98k stars 6.68k forks source link

stm32l0: Voltage regulator is not restored after leaving STOP mode #42092

Closed abxy closed 2 years ago

abxy commented 2 years ago

Describe the bug I have a custom board that started to crash after I enabled power management. I have located the source of the problem to the cpu power management driver for STM32L0.

In power.c, when entering "STOP mode" (suspend to idle) the internal voltage regulator is changed to low-power mode, but when exiting STOP mode, the regulator mode is not restored to its main mode. Specifically it is the LPSDSR bit of PWR_CR that is not restored. It is my understanding that leaving this bit set will cause the MCU to enter "low-power sleep" in the idle thread, but that requires additional steps to do safely. This is further corroborated by the fact that my attempts to debug the issue indicates a fault in arch_cpu_idle.

To Reproduce

Reproducing the stability issue is difficult as it seems to depend on other factors (my own untested hypothesis is that having VDD = 1.8V can be a contributing factor). I have only had it happen on a custom board, but on that board it is very reproducible.

I cannot give full steps to reproduce, but the sample samples/boards/stm32/power_mgmt/blinky can be modified to verify that regulator is indeed configured to low-power mode after entering STOP mode for the first time.

In main.c...

...include the relevant header

#include <stm32_ll_pwr.h>

...and modify the loop

while (true) {
        printk("Regulator mode LP: 0x%x\n", LL_PWR_GetRegulModeLP());
        /* Rest of the loop body */
}

Add DTS overlay if needed. E.g. boards/nucleo_l031k6.overlay:

/ {
    power-states {
        stop: stop {
            compatible = "zephyr,power-state";
            power-state-name = "suspend-to-idle";
            min-residency-us = <100>;
        };
    };
};

&cpu0 {
    cpu-power-states = <&stop>;
};

&lptim1 {
    status = "okay";
};

Build and run

  1. west build -b nucleo_l031k6 -s samples/boards/stm32/power_mgmt/blinky
  2. west flash
  3. Open terminal to view output

Output showing that regulator mode changes:

*** Booting Zephyr OS build v2.7.99-3661-gd51a67b7c098  ***
Device ready
Regulator mode LP: 0x0
Regulator mode LP: 0x1
Regulator mode LP: 0x1
Regulator mode LP: 0x1

Expected behavior All lines should print Regulator mode LP: 0x0. My custom board should not crash.

Additional context The custom board on which this issue was first observed uses uses STM32L071CZ, sys clock = HSI16 and VDD = 1.8V.

wcappelle commented 2 years ago

Great fix, I've experienced the same problems with an STM32L010RB board (even sometimes on the nucleo board with external -unstable- power). I've tried your fix, and so far no problems, but as you said reproduction isn't that easy..