Skip to content

Commit b3f7394

Browse files
Desvauxm-stcarlescufi
authored andcommitted
samples: boards: stm32: Power_mgmt: sample for standby shutdownn mode
STM32L4x power management (ultra_low_power) of Standby mode and shutdown mode Signed-off-by: Marc Desvaux <[email protected]>
1 parent ba44549 commit b3f7394

File tree

5 files changed

+232
-0
lines changed

5 files changed

+232
-0
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
cmake_minimum_required(VERSION 3.20.0)
4+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
5+
project(stm32_pm_standby_shutdown)
6+
7+
target_sources(app PRIVATE src/main.c)
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
.. _stm32-pm-standby_shutdown-sample:
2+
3+
STM32 PM Standby shutdown
4+
#########################
5+
6+
Overview
7+
********
8+
9+
This sample is a minimum application to demonstrate basic power management of Standby mode and
10+
shutdown mode
11+
behavior in a basic blinking LED set up you can enter in shutdown mode or in standbymode mode.
12+
Press and hold the user button:
13+
when LED2 is OFF to enter to Shutdown Mode
14+
when LED2 is ON to enter to Standby Mode
15+
release the user button to exit from shutdown mode or from shutdown mode.
16+
17+
.. _stm32-pm-standby_shutdown-sample-requirements:
18+
19+
Requirements
20+
************
21+
22+
The board should support enabling PM. For a STM32 based target, it means that
23+
it should support a clock source alternative to Cortex Systick that can be used
24+
in core sleep states, as LPTIM (:dtcompatible:`st,stm32-lptim`).
25+
For another board than nucleo_L476RG please adjust wakeup pin into config_wakeup_features().
26+
27+
Building and Running
28+
********************
29+
30+
Build and flash standby_shutdown as follows, changing ``nucleo_L476RG`` for your board:
31+
32+
.. zephyr-app-commands::
33+
:zephyr-app: samples/samples/boards/stm32/power_mgmt/standby_shutdown
34+
:board: nucleo_L476RG
35+
:goals: build flash
36+
:compact:
37+
38+
After flashing, the LED starts to blink.
39+
Press and hold the user button:
40+
when LED2 is OFF to enter to Shutdown Mode
41+
when LED2 is ON to enter to Standby Mode
42+
release the user button to exit from shutdown mode or from shutdown mode.
43+
44+
PM configurations
45+
*****************
46+
47+
By default, :kconfig:option:`CONFIG_PM` is enabled.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
CONFIG_PM=y
2+
CONFIG_PM_DEVICE=n
3+
CONFIG_PM_DEVICE_RUNTIME=n
4+
CONFIG_HWINFO=y
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
sample:
2+
name: STM32 GPIO Power Management
3+
tests:
4+
sample.boards.stm32.power_mgmt.standby_shutdown:
5+
platform_allow: nucleo_l476rg disco_l475_iot1
6+
tags: LED power
7+
harness: console
8+
harness_config:
9+
type: multi_line
10+
regex:
11+
- "Reset cause: Reset pin"
12+
- "Device ready: .*"
13+
- "Press and hold the user button:"
14+
- "when LED2 is OFF to enter to Shutdown Mode"
15+
- "when LED2 is ON to enter to Standby Mode"
16+
filter: dt_compat_enabled("zephyr,power-state") and
17+
dt_enabled_alias_with_parent_compat("led0", "gpio-leds") and
18+
dt_compat_enabled("st,stm32-lptim")
19+
extra_args: "CONFIG_DEBUG=y"
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
/*
2+
* Copyright (c) 2023 STMicroelectronics
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/drivers/hwinfo.h>
8+
#include <zephyr/kernel.h>
9+
#include <zephyr/device.h>
10+
#include <zephyr/devicetree.h>
11+
#include <zephyr/drivers/gpio.h>
12+
#include <zephyr/sys/printk.h>
13+
#include <zephyr/pm/pm.h>
14+
#include <stm32_ll_pwr.h>
15+
16+
#if !defined(CONFIG_SOC_SERIES_STM32L4X)
17+
#error Not implemented for other series
18+
#endif /* CONFIG_SOC_SERIES_STM32L4X */
19+
20+
#define STACKSIZE 1024
21+
#define PRIORITY 7
22+
#define SLEEP_TIME_MS 3000
23+
24+
#define SW0_NODE DT_ALIAS(sw0)
25+
#if !DT_NODE_HAS_STATUS(SW0_NODE, okay)
26+
#error "Unsupported board: sw0 devicetree alias is not defined"
27+
#endif
28+
29+
/* Semaphore used to control button pressed value */
30+
static struct k_sem button_sem;
31+
32+
static int led_is_on;
33+
34+
static const struct gpio_dt_spec button =
35+
GPIO_DT_SPEC_GET_OR(SW0_NODE, gpios, {0});
36+
37+
static const struct gpio_dt_spec led =
38+
GPIO_DT_SPEC_GET(DT_ALIAS(led0), gpios);
39+
40+
static struct gpio_callback button_cb_data;
41+
42+
void config_wakeup_features(void)
43+
{
44+
/* Configure wake-up features */
45+
/* WKUP2(PC13) only , - active low, pull-up */
46+
/* Set pull-ups for standby modes */
47+
LL_PWR_EnableGPIOPullUp(LL_PWR_GPIO_C, LL_PWR_GPIO_BIT_13);
48+
LL_PWR_IsWakeUpPinPolarityLow(LL_PWR_WAKEUP_PIN2);
49+
/* Enable pin pull up configurations and wakeup pins */
50+
LL_PWR_EnablePUPDCfg();
51+
LL_PWR_EnableWakeUpPin(LL_PWR_WAKEUP_PIN2);
52+
/* Clear wakeup flags */
53+
LL_PWR_ClearFlag_WU();
54+
}
55+
56+
void button_pressed(const struct device *dev, struct gpio_callback *cb,
57+
uint32_t pins)
58+
{
59+
k_sem_give(&button_sem);
60+
}
61+
62+
void thread_shutdown_standby_mode(void)
63+
{
64+
k_sem_init(&button_sem, 0, 1);
65+
k_sem_take(&button_sem, K_FOREVER);
66+
gpio_pin_configure(led.port, led.pin, GPIO_DISCONNECTED);
67+
printk("User button pressed\n");
68+
config_wakeup_features();
69+
if (led_is_on == false) {
70+
printk("Shutdown Mode requested\n");
71+
printk("Release the user button to exit from Shutdown Mode\n\n");
72+
#ifdef CONFIG_LOG
73+
k_msleep(2000);
74+
#endif /* CONFIG_LOG */
75+
pm_state_force(0u, &(struct pm_state_info) {PM_STATE_SOFT_OFF, 0, 0});
76+
/* stay in Shutdown mode until wakeup line activated */
77+
} else {
78+
printk("Standby Mode requested\n");
79+
printk("Release the user button to exit from Standby Mode\n\n");
80+
#ifdef CONFIG_LOG
81+
k_msleep(2000);
82+
#endif /* CONFIG_LOG */
83+
pm_state_force(0u, &(struct pm_state_info) {PM_STATE_STANDBY, 0, 0});
84+
/* stay in Standby mode until wakeup line activated */
85+
}
86+
}
87+
88+
K_THREAD_DEFINE(thread_shutdown_standby_mode_id, STACKSIZE, thread_shutdown_standby_mode,
89+
NULL, NULL, NULL, PRIORITY, 0, 0);
90+
91+
void main(void)
92+
{
93+
int ret;
94+
uint32_t cause;
95+
96+
hwinfo_get_reset_cause(&cause);
97+
hwinfo_clear_reset_cause();
98+
99+
if ((LL_PWR_IsActiveFlag_SB() == true) && (cause == 0)) {
100+
LL_PWR_ClearFlag_SB();
101+
LL_PWR_ClearFlag_WU();
102+
printk("\nReset cause: Standby mode\n\n");
103+
}
104+
105+
if (cause == (RESET_PIN | RESET_BROWNOUT)) {
106+
LL_PWR_ClearFlag_WU();
107+
printk("\nReset cause: Shutdown mode or power up\n\n");
108+
}
109+
110+
if (cause == RESET_PIN) {
111+
LL_PWR_ClearFlag_WU();
112+
printk("\nReset cause: Reset pin\n\n");
113+
}
114+
115+
116+
__ASSERT_NO_MSG(device_is_ready(led.port));
117+
if (!gpio_is_ready_dt(&button)) {
118+
printk("Error: button device %s is not ready\n",
119+
button.port->name);
120+
return;
121+
}
122+
123+
ret = gpio_pin_configure_dt(&button, GPIO_INPUT);
124+
if (ret != 0) {
125+
printk("Error %d: failed to configure %s pin %d\n",
126+
ret, button.port->name, button.pin);
127+
return;
128+
}
129+
130+
ret = gpio_pin_interrupt_configure_dt(&button,
131+
GPIO_INT_EDGE_TO_ACTIVE);
132+
if (ret != 0) {
133+
printk("Error %d: failed to configure interrupt on %s pin %d\n",
134+
ret, button.port->name, button.pin);
135+
return;
136+
}
137+
138+
gpio_init_callback(&button_cb_data, button_pressed, BIT(button.pin));
139+
gpio_add_callback(button.port, &button_cb_data);
140+
141+
printk("Device ready: %s\n\n\n", CONFIG_BOARD);
142+
143+
printk("Press and hold the user button:\n");
144+
printk(" when LED2 is OFF to enter to Shutdown Mode\n");
145+
printk(" when LED2 is ON to enter to Standby Mode\n\n");
146+
147+
led_is_on = true;
148+
while (true) {
149+
gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE);
150+
gpio_pin_set(led.port, led.pin, (int)led_is_on);
151+
k_msleep(SLEEP_TIME_MS);
152+
led_is_on = !led_is_on;
153+
}
154+
155+
}

0 commit comments

Comments
 (0)