Skip to content

Commit 585cda1

Browse files
Oleh-Kravchenkocfriedt
authored andcommitted
soc: stm32l1x: Add support for sleep/stop/standby modes
Add stm32l1_disco and nucleo_l152re overlays for testing sleep/stop/standby modes: - samples/boards/st/power_mgmt/blinky; - samples/boards/st/power_mgmt/wkup_pins; I've measured consumption for each low-power mode: - low-power sleep ~1.72mA; - stop mode ~324uA; - standby mode ~2.2 uA; It's possible to use RTC as idle timer to exit from stop mode. Signed-off-by: Oleh Kravchenko <[email protected]>
1 parent 9a9f060 commit 585cda1

File tree

10 files changed

+196
-7
lines changed

10 files changed

+196
-7
lines changed

dts/arm/st/l1/stm32l1.dtsi

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@
1616
#include <zephyr/dt-bindings/dma/stm32_dma.h>
1717
#include <zephyr/dt-bindings/adc/stm32f4_adc.h>
1818
#include <zephyr/dt-bindings/reset/stm32l1_reset.h>
19+
#include <zephyr/dt-bindings/power/stm32_pwr.h>
1920
#include <freq.h>
2021

2122
/ {
2223
chosen {
2324
zephyr,flash-controller = &flash;
25+
zephyr,cortex-m-idle-timer = &rtc;
2426
};
2527

2628
cpus {
@@ -30,10 +32,27 @@
3032
cpu0: cpu@0 {
3133
device_type = "cpu";
3234
compatible = "arm,cortex-m3";
35+
cpu-power-states = <&sleep &stop>;
3336
reg = <0>;
3437
};
3538
};
3639

40+
power-states {
41+
sleep: sleep {
42+
compatible = "zephyr,power-state";
43+
power-state-name = "runtime-idle";
44+
min-residency-us = <1000000>;
45+
exit-latency-us = <750>;
46+
};
47+
48+
stop: stop {
49+
compatible = "zephyr,power-state";
50+
power-state-name = "suspend-to-idle";
51+
min-residency-us = <1000000>;
52+
exit-latency-us = <750>;
53+
};
54+
};
55+
3756
sram0: memory@20000000 {
3857
compatible = "mmio-sram";
3958
};
@@ -81,7 +100,6 @@
81100
};
82101

83102
soc {
84-
85103
flash: flash-controller@40023c00 {
86104
compatible = "st,stm32-flash-controller", "st,stm32f1-flash-controller";
87105
reg = <0x40023c00 0x400>;
@@ -184,6 +202,32 @@
184202
status = "disabled";
185203
};
186204

205+
pwr: power@40007000 {
206+
compatible = "st,stm32-pwr";
207+
reg = <0x40007000 0x400>; /* PWR register bank */
208+
status = "disabled";
209+
210+
wkup-pins-nb = <3>;
211+
212+
#address-cells = <1>;
213+
#size-cells = <0>;
214+
215+
wkup-pin@1 {
216+
reg = <0x1>;
217+
wkup-gpios = <&gpioa 0 STM32_PWR_WKUP_PIN_NOT_MUXED>;
218+
};
219+
220+
wkup-pin@2 {
221+
reg = <0x2>;
222+
wkup-gpios = <&gpioc 13 STM32_PWR_WKUP_PIN_NOT_MUXED>;
223+
};
224+
225+
wkup-pin@3 {
226+
reg = <0x3>;
227+
wkup-gpios = <&gpioe 6 STM32_PWR_WKUP_PIN_NOT_MUXED>;
228+
};
229+
};
230+
187231
spi1: spi@40013000 {
188232
compatible = "st,stm32-spi";
189233
#address-cells = <1>;
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*
2+
* Copyright (c) 2025 Oleh Kravchenko <[email protected]>
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/ {
8+
aliases {
9+
wkup-src = &user_button;
10+
};
11+
};
12+
13+
&pwr {
14+
status = "okay";
15+
};
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*
2+
* Copyright (c) 2025 Oleh Kravchenko <[email protected]>
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/ {
8+
aliases {
9+
wkup-src = &user_button;
10+
};
11+
};
12+
13+
&pwr {
14+
status = "okay";
15+
};

samples/boards/st/power_mgmt/wkup_pins/sample.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,7 @@ tests:
1212
- nucleo_u5a5zj_q
1313
- nucleo_wl55jc
1414
- nucleo_f103rb
15+
- stm32l1_disco
16+
- nucleo_l152re
1517
integration_platforms:
1618
- nucleo_l4r5zi

soc/st/stm32/common/soc_config.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ static int st_stm32_common_config(void)
6969

7070
#if defined(CONFIG_STM32_ENABLE_DEBUG_SLEEP_STOP)
7171

72-
#if defined(CONFIG_SOC_SERIES_STM32F1X)
72+
#if defined(CONFIG_SOC_SERIES_STM32F1X) || defined(CONFIG_SOC_SERIES_STM32L1X)
7373
LL_DBGMCU_EnableDBGSleepMode();
7474
LL_DBGMCU_EnableDBGStopMode();
7575
LL_DBGMCU_EnableDBGStandbyMode();
@@ -89,7 +89,7 @@ static int st_stm32_common_config(void)
8989
#else
9090

9191
/* keeping in mind that debugging draws a lot of power we explcitly disable when not needed */
92-
#if defined(CONFIG_SOC_SERIES_STM32F1X)
92+
#if defined(CONFIG_SOC_SERIES_STM32F1X) || defined(CONFIG_SOC_SERIES_STM32L1X)
9393
LL_DBGMCU_DisableDBGSleepMode();
9494
LL_DBGMCU_DisableDBGStopMode();
9595
LL_DBGMCU_DisableDBGStandbyMode();

soc/st/stm32/stm32l1x/CMakeLists.txt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
13
zephyr_include_directories(${ZEPHYR_BASE}/drivers)
2-
zephyr_sources(
3-
soc.c
4-
)
4+
zephyr_sources(soc.c)
5+
6+
zephyr_sources_ifdef(CONFIG_PM power.c)
7+
zephyr_sources_ifdef(CONFIG_POWEROFF poweroff.c)
58

69
zephyr_include_directories(.)
710

soc/st/stm32/stm32l1x/Kconfig

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ config SOC_SERIES_STM32L1X
77
select ARM
88
select CPU_CORTEX_M3
99
select CPU_CORTEX_M_HAS_DWT
10+
select CPU_HAS_ARM_MPU
11+
select HAS_PM
12+
select HAS_POWEROFF
1013
select HAS_STM32CUBE
1114
select HAS_SWO
12-
select CPU_HAS_ARM_MPU
1315
select SOC_EARLY_INIT_HOOK

soc/st/stm32/stm32l1x/Kconfig.defconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,11 @@ config TASK_WDT_HW_FALLBACK_DELAY
1212
depends on TASK_WDT_HW_FALLBACK
1313
default 200
1414

15+
if PM
16+
17+
config COUNTER
18+
default y
19+
20+
endif # PM
21+
1522
endif # SOC_SERIES_STM32L1X

soc/st/stm32/stm32l1x/power.c

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Copyright (c) 2025 Oleh Kravchenko <[email protected]>
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <clock_control/clock_stm32_ll_common.h>
8+
#include <stm32l1xx_ll_cortex.h>
9+
#include <stm32l1xx_ll_pwr.h>
10+
11+
#include <zephyr/kernel.h>
12+
#include <zephyr/logging/log.h>
13+
#include <zephyr/pm/pm.h>
14+
15+
LOG_MODULE_DECLARE(soc, CONFIG_SOC_LOG_LEVEL);
16+
17+
__weak void pm_state_set(enum pm_state state, uint8_t substate_id)
18+
{
19+
switch (state) {
20+
case PM_STATE_RUNTIME_IDLE:
21+
LL_LPM_DisableEventOnPend();
22+
LL_PWR_ClearFlag_WU();
23+
24+
LL_PWR_SetRegulModeLP(LL_PWR_REGU_LPMODES_LOW_POWER);
25+
LL_PWR_SetPowerMode(LL_PWR_MODE_STOP);
26+
LL_LPM_EnableSleep();
27+
28+
k_cpu_idle();
29+
break;
30+
31+
case PM_STATE_SUSPEND_TO_IDLE:
32+
LL_LPM_DisableEventOnPend();
33+
LL_PWR_ClearFlag_WU();
34+
35+
LL_PWR_SetRegulModeLP(LL_PWR_REGU_LPMODES_LOW_POWER);
36+
LL_PWR_SetPowerMode(LL_PWR_MODE_STOP);
37+
LL_LPM_EnableDeepSleep();
38+
39+
k_cpu_idle();
40+
break;
41+
42+
default:
43+
LOG_DBG("Unsupported power state %u", state);
44+
break;
45+
}
46+
}
47+
48+
__weak void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id)
49+
{
50+
ARG_UNUSED(substate_id);
51+
52+
switch (state) {
53+
case PM_STATE_RUNTIME_IDLE:
54+
LL_PWR_SetRegulModeLP(LL_PWR_REGU_LPMODES_MAIN);
55+
break;
56+
57+
case PM_STATE_SUSPEND_TO_IDLE:
58+
LL_LPM_DisableSleepOnExit();
59+
LL_LPM_EnableSleep();
60+
LL_PWR_SetRegulModeLP(LL_PWR_REGU_LPMODES_MAIN);
61+
62+
/* Restore the clock setup. */
63+
stm32_clock_control_init(NULL);
64+
break;
65+
66+
default:
67+
LOG_DBG("Unsupported power substate-id %u", state);
68+
break;
69+
}
70+
71+
/*
72+
* System is now in active mode. Reenable interrupts which were
73+
* disabled when OS started idling code.
74+
*/
75+
irq_unlock(0);
76+
}

soc/st/stm32/stm32l1x/poweroff.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright (c) 2025 Oleh Kravchenko <[email protected]>
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <stm32l1xx_ll_cortex.h>
8+
#include <stm32l1xx_ll_pwr.h>
9+
10+
#include <zephyr/kernel.h>
11+
#include <zephyr/sys/poweroff.h>
12+
13+
void z_sys_poweroff(void)
14+
{
15+
LL_PWR_ClearFlag_SB();
16+
LL_PWR_ClearFlag_WU();
17+
18+
LL_LPM_DisableEventOnPend();
19+
LL_PWR_SetPowerMode(LL_PWR_MODE_STANDBY);
20+
LL_LPM_EnableDeepSleep();
21+
22+
k_cpu_idle();
23+
24+
CODE_UNREACHABLE;
25+
}

0 commit comments

Comments
 (0)