soc: arm: st_stm32 add low power to stm32wb series

This patch introduces the support of low power modes
for the STM32WBxx from STMicroelectronics based on the lptim
Here, the power modes are sleep modes have lptimer as wakeup source.
The sleep modes are configured by the SYS_POWER_MANAGEMENT.

Signed-off-by: Francois Ramu <francois.ramu@st.com>
This commit is contained in:
Francois Ramu 2020-06-09 09:50:01 +02:00 committed by Anas Nashif
commit fd5ce64db4
5 changed files with 141 additions and 1 deletions

View file

@ -7,3 +7,7 @@ zephyr_linker_sources_ifdef(CONFIG_BT_STM32_IPM
SECTIONS
ipm.ld
)
zephyr_sources_ifdef(CONFIG_SYS_POWER_MANAGEMENT
power.c
)

View file

@ -10,6 +10,11 @@ source "soc/arm/st_stm32/stm32wb/Kconfig.defconfig.stm32wb*"
config SOC_SERIES
default "stm32wb"
config STM32_LPTIM_TIMER
bool
default y
depends on SYS_POWER_MANAGEMENT
config DMA_STM32_V2
default y
depends on DMA_STM32

View file

@ -13,5 +13,8 @@ config SOC_SERIES_STM32WBX
select HAS_STM32CUBE
select CPU_HAS_ARM_MPU
select HAS_SWO
select HAS_SYS_POWER_STATE_SLEEP_1
select HAS_SYS_POWER_STATE_SLEEP_2
select HAS_SYS_POWER_STATE_SLEEP_3
help
Enable support for STM32WB MCU series

View file

@ -0,0 +1,128 @@
/*
* Copyright (c) 2019 STMicroelectronics.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr.h>
#include <power/power.h>
#include <soc.h>
#include <init.h>
#include <stm32wbxx_ll_bus.h>
#include <stm32wbxx_ll_cortex.h>
#include <stm32wbxx_ll_pwr.h>
#include <stm32wbxx_ll_rcc.h>
#include <logging/log.h>
LOG_MODULE_DECLARE(soc, CONFIG_SOC_LOG_LEVEL);
/* Invoke Low Power/System Off specific Tasks */
void sys_set_power_state(enum power_states state)
{
switch (state) {
#ifdef CONFIG_SYS_POWER_SLEEP_STATES
#ifdef CONFIG_HAS_SYS_POWER_STATE_SLEEP_1
case SYS_POWER_STATE_SLEEP_1:
/* this corresponds to the STOP0 mode: */
#ifdef CONFIG_DEBUG
/* Enable the Debug Module during STOP mode */
LL_DBGMCU_EnableDBGStopMode();
#endif /* CONFIG_DEBUG */
/* ensure HSI is the wake-up system clock */
LL_RCC_SetClkAfterWakeFromStop(LL_RCC_STOP_WAKEUPCLOCK_HSI);
/* enter STOP0 mode */
LL_PWR_SetPowerMode(LL_PWR_MODE_STOP0);
LL_LPM_EnableDeepSleep();
/* enter SLEEP mode : WFE or WFI */
k_cpu_idle();
break;
#endif /* CONFIG_HAS_SYS_POWER_STATE_SLEEP_1 */
#ifdef CONFIG_HAS_SYS_POWER_STATE_SLEEP_2
case SYS_POWER_STATE_SLEEP_2:
/* this corresponds to the STOP1 mode: */
#ifdef CONFIG_DEBUG
/* Enable the Debug Module during STOP mode */
LL_DBGMCU_EnableDBGStopMode();
#endif /* CONFIG_DEBUG */
/* ensure HSI is the wake-up system clock */
LL_RCC_SetClkAfterWakeFromStop(LL_RCC_STOP_WAKEUPCLOCK_HSI);
/* enter STOP1 mode */
LL_PWR_SetPowerMode(LL_PWR_MODE_STOP1);
LL_LPM_EnableDeepSleep();
k_cpu_idle();
break;
#endif /* CONFIG_HAS_SYS_POWER_STATE_SLEEP_2 */
#ifdef CONFIG_HAS_SYS_POWER_STATE_SLEEP_3
case SYS_POWER_STATE_SLEEP_3:
/* this corresponds to the STOP2 mode: */
#ifdef CONFIG_DEBUG
/* Enable the Debug Module during STOP mode */
LL_DBGMCU_EnableDBGStopMode();
#endif /* CONFIG_DEBUG */
/* ensure HSI is the wake-up system clock */
LL_RCC_SetClkAfterWakeFromStop(LL_RCC_STOP_WAKEUPCLOCK_HSI);
#ifdef PWR_CR1_RRSTP
LL_PWR_DisableSRAM3Retention();
#endif /* PWR_CR1_RRSTP */
/* enter STOP2 mode */
LL_PWR_SetPowerMode(LL_PWR_MODE_STOP2);
LL_LPM_EnableDeepSleep();
k_cpu_idle();
break;
#endif /* CONFIG_HAS_SYS_POWER_STATE_SLEEP_3 */
#endif /* CONFIG_SYS_POWER_SLEEP_STATES */
default:
LOG_DBG("Unsupported power state %u", state);
break;
}
}
/* Handle SOC specific activity after Low Power Mode Exit */
void _sys_pm_power_state_exit_post_ops(enum power_states state)
{
switch (state) {
#ifdef CONFIG_SYS_POWER_SLEEP_STATES
#ifdef CONFIG_HAS_SYS_POWER_STATE_SLEEP_1
case SYS_POWER_STATE_SLEEP_1:
#endif /* CONFIG_HAS_SYS_POWER_STATE_SLEEP_1 */
#ifdef CONFIG_HAS_SYS_POWER_STATE_SLEEP_2
case SYS_POWER_STATE_SLEEP_2:
#endif /* CONFIG_HAS_SYS_POWER_STATE_SLEEP_2 */
#ifdef CONFIG_HAS_SYS_POWER_STATE_SLEEP_3
case SYS_POWER_STATE_SLEEP_3:
#endif /* CONFIG_HAS_SYS_POWER_STATE_SLEEP_3 */
LL_LPM_DisableSleepOnExit();
break;
#endif /* CONFIG_SYS_POWER_SLEEP_STATES */
default:
LOG_DBG("Unsupported power state %u", state);
break;
}
/*
* System is now in active mode.
* Reenable interrupts which were disabled
* when OS started idling code.
*/
irq_unlock(0);
}
/* Initialize STM32 Power */
static int stm32_power_init(struct device *dev)
{
unsigned int ret;
ARG_UNUSED(dev);
ret = irq_lock();
/* enable Power clock */
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR);
irq_unlock(ret);
return 0;
}
SYS_INIT(stm32_power_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);

View file

@ -45,7 +45,7 @@ static const char *const core_devices[] = {
static const char *const core_devices[] = {
"",
};
#elif defined(CONFIG_SOC_SERIES_STM32L4X)
#elif defined(CONFIG_SOC_SERIES_STM32L4X) || defined(CONFIG_SOC_SERIES_STM32WBX)
#define MAX_PM_DEVICES 1
static const char *const core_devices[] = {
"sys_clock",