soc: arm: stm32wba: add support for standby mode with ram retention
Add support for STM32WBA Standby low-power mode with RAM retention. Signed-off-by: Guillaume Gautier <guillaume.gautier-ext@st.com>
This commit is contained in:
parent
624139ad9a
commit
6b681bcbcc
4 changed files with 131 additions and 23 deletions
|
@ -39,4 +39,26 @@ config ENTROPY_STM32_CLK_CHECK
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if PM_S2RAM
|
||||||
|
|
||||||
|
config COUNTER
|
||||||
|
default y
|
||||||
|
|
||||||
|
config COUNTER_RTC_STM32_SUBSECONDS
|
||||||
|
default y
|
||||||
|
|
||||||
|
config STM32_LPTIM_STDBY_TIMER
|
||||||
|
default y
|
||||||
|
|
||||||
|
config TICKLESS_KERNEL
|
||||||
|
default y
|
||||||
|
|
||||||
|
config COUNTER_RTC_STM32_SAVE_VALUE_BETWEEN_RESETS
|
||||||
|
default y
|
||||||
|
|
||||||
|
config IDLE_STACK_SIZE
|
||||||
|
default 512
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
endif # SOC_SERIES_STM32WBAX
|
endif # SOC_SERIES_STM32WBAX
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
#include <zephyr/pm/pm.h>
|
#include <zephyr/pm/pm.h>
|
||||||
#include <soc.h>
|
#include <soc.h>
|
||||||
#include <zephyr/init.h>
|
#include <zephyr/init.h>
|
||||||
|
#include <zephyr/arch/common/pm_s2ram.h>
|
||||||
|
#include <zephyr/drivers/timer/system_timer.h>
|
||||||
|
|
||||||
#include <stm32wbaxx_ll_bus.h>
|
#include <stm32wbaxx_ll_bus.h>
|
||||||
#include <stm32wbaxx_ll_cortex.h>
|
#include <stm32wbaxx_ll_cortex.h>
|
||||||
|
@ -24,7 +26,25 @@
|
||||||
|
|
||||||
LOG_MODULE_DECLARE(soc, CONFIG_SOC_LOG_LEVEL);
|
LOG_MODULE_DECLARE(soc, CONFIG_SOC_LOG_LEVEL);
|
||||||
|
|
||||||
void set_mode_stop(uint8_t substate_id)
|
static int stm32_power_init(void);
|
||||||
|
|
||||||
|
static void disable_cache(void)
|
||||||
|
{
|
||||||
|
/* Disabling ICACHE */
|
||||||
|
LL_ICACHE_Disable();
|
||||||
|
while (LL_ICACHE_IsEnabled() == 1U) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait until ICACHE_SR.BUSYF is cleared */
|
||||||
|
while (LL_ICACHE_IsActiveFlag_BUSY() == 1U) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait until ICACHE_SR.BSYENDF is set */
|
||||||
|
while (LL_ICACHE_IsActiveFlag_BSYEND() == 0U) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_mode_stop(uint8_t substate_id)
|
||||||
{
|
{
|
||||||
|
|
||||||
LL_PWR_ClearFlag_STOP();
|
LL_PWR_ClearFlag_STOP();
|
||||||
|
@ -33,10 +53,7 @@ void set_mode_stop(uint8_t substate_id)
|
||||||
/* Erratum 2.2.15:
|
/* Erratum 2.2.15:
|
||||||
* Disabling ICACHE is required before entering stop mode
|
* Disabling ICACHE is required before entering stop mode
|
||||||
*/
|
*/
|
||||||
LL_ICACHE_Disable();
|
disable_cache();
|
||||||
while (LL_ICACHE_IsEnabled() == 1U) {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_BT_STM32WBA
|
#ifdef CONFIG_BT_STM32WBA
|
||||||
scm_setwaitstates(LP);
|
scm_setwaitstates(LP);
|
||||||
|
@ -60,35 +77,76 @@ void set_mode_stop(uint8_t substate_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_PM_S2RAM)
|
||||||
|
static int suspend_to_ram(void)
|
||||||
|
{
|
||||||
|
LL_LPM_EnableDeepSleep();
|
||||||
|
|
||||||
|
while (LL_PWR_IsActiveFlag_ACTVOS() == 0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Select mode entry : WFE or WFI and enter the CPU selected mode */
|
||||||
|
k_cpu_idle();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_mode_suspend_to_ram(void)
|
||||||
|
{
|
||||||
|
/* Enable SRAM full retention */
|
||||||
|
LL_PWR_SetSRAM1SBRetention(LL_PWR_SRAM1_SB_FULL_RETENTION);
|
||||||
|
LL_PWR_SetSRAM2SBRetention(LL_PWR_SRAM2_SB_FULL_RETENTION);
|
||||||
|
|
||||||
|
/* Enable RTC wakeup
|
||||||
|
* This configures an internal pin that generates an event to wakeup the system
|
||||||
|
*/
|
||||||
|
LL_PWR_EnableWakeUpPin(LL_PWR_WAKEUP_PIN7);
|
||||||
|
LL_PWR_SetWakeUpPinSignal3Selection(LL_PWR_WAKEUP_PIN7);
|
||||||
|
|
||||||
|
/* Clear flags */
|
||||||
|
LL_PWR_ClearFlag_SB();
|
||||||
|
LL_PWR_ClearFlag_WU();
|
||||||
|
LL_RCC_ClearResetFlags();
|
||||||
|
|
||||||
|
disable_cache();
|
||||||
|
|
||||||
|
/* Select standby mode */
|
||||||
|
LL_PWR_SetPowerMode(LL_PWR_MODE_STANDBY);
|
||||||
|
|
||||||
|
/* Save context and enter Standby mode */
|
||||||
|
arch_pm_s2ram_suspend(suspend_to_ram);
|
||||||
|
|
||||||
|
/* Execution is restored at this point after wake up */
|
||||||
|
/* Restore system clock as soon as we exit standby mode */
|
||||||
|
sys_clock_idle_exit();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Invoke Low Power/System Off specific Tasks */
|
/* Invoke Low Power/System Off specific Tasks */
|
||||||
void pm_state_set(enum pm_state state, uint8_t substate_id)
|
void pm_state_set(enum pm_state state, uint8_t substate_id)
|
||||||
{
|
{
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case PM_STATE_SUSPEND_TO_IDLE:
|
case PM_STATE_SUSPEND_TO_IDLE:
|
||||||
set_mode_stop(substate_id);
|
set_mode_stop(substate_id);
|
||||||
|
|
||||||
|
/* Select mode entry : WFE or WFI and enter the CPU selected mode */
|
||||||
|
k_cpu_idle();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case PM_STATE_STANDBY:
|
#if defined(CONFIG_PM_S2RAM)
|
||||||
/* Not supported today */
|
case PM_STATE_SUSPEND_TO_RAM:
|
||||||
__fallthrough;
|
set_mode_suspend_to_ram();
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
LOG_DBG("Unsupported power state %u", state);
|
LOG_DBG("Unsupported power state %u", state);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Select mode entry : WFE or WFI and enter the CPU selected mode */
|
|
||||||
k_cpu_idle();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle SOC specific activity after Low Power Mode Exit */
|
/* Handle SOC specific activity after Low Power Mode Exit */
|
||||||
void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id)
|
void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id)
|
||||||
{
|
{
|
||||||
/* Erratum 2.2.15:
|
|
||||||
* Enable ICACHE when exiting stop mode
|
|
||||||
*/
|
|
||||||
LL_ICACHE_Enable();
|
|
||||||
while (LL_ICACHE_IsEnabled() == 0U) {
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_BT_STM32WBA
|
#ifdef CONFIG_BT_STM32WBA
|
||||||
if (LL_PWR_IsActiveFlag_STOP() == 1U) {
|
if (LL_PWR_IsActiveFlag_STOP() == 1U) {
|
||||||
scm_setup();
|
scm_setup();
|
||||||
|
@ -100,16 +158,33 @@ void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id)
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case PM_STATE_SUSPEND_TO_IDLE:
|
case PM_STATE_SUSPEND_TO_IDLE:
|
||||||
if (substate_id <= 2) {
|
if (substate_id <= 2) {
|
||||||
|
/* Erratum 2.2.15:
|
||||||
|
* Enable ICACHE when exiting stop mode
|
||||||
|
*/
|
||||||
|
LL_ICACHE_SetMode(LL_ICACHE_1WAY);
|
||||||
|
LL_ICACHE_Enable();
|
||||||
|
while (LL_ICACHE_IsEnabled() == 0U) {
|
||||||
|
}
|
||||||
|
|
||||||
LL_LPM_DisableSleepOnExit();
|
LL_LPM_DisableSleepOnExit();
|
||||||
LL_LPM_EnableSleep();
|
LL_LPM_EnableSleep();
|
||||||
} else {
|
} else {
|
||||||
LOG_DBG("Unsupported power substate-id %u",
|
LOG_DBG("Unsupported power substate-id %u",
|
||||||
substate_id);
|
substate_id);
|
||||||
}
|
}
|
||||||
case PM_STATE_STANDBY:
|
break;
|
||||||
/* To be tested */
|
|
||||||
LL_LPM_EnableSleep();
|
|
||||||
case PM_STATE_SUSPEND_TO_RAM:
|
case PM_STATE_SUSPEND_TO_RAM:
|
||||||
|
#if defined(CONFIG_PM_S2RAM)
|
||||||
|
stm32wba_init();
|
||||||
|
stm32_power_init();
|
||||||
|
|
||||||
|
LL_LPM_DisableSleepOnExit();
|
||||||
|
LL_LPM_EnableSleep();
|
||||||
|
#else
|
||||||
|
LOG_DBG("Suspend to RAM needs CONFIG_PM_S2RAM to be enabled");
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case PM_STATE_STANDBY:
|
||||||
__fallthrough;
|
__fallthrough;
|
||||||
case PM_STATE_SUSPEND_TO_DISK:
|
case PM_STATE_SUSPEND_TO_DISK:
|
||||||
__fallthrough;
|
__fallthrough;
|
||||||
|
@ -141,6 +216,15 @@ static int stm32_power_init(void)
|
||||||
|
|
||||||
LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_PWR);
|
LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_PWR);
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG
|
||||||
|
LL_DBGMCU_EnableDBGStandbyMode();
|
||||||
|
LL_DBGMCU_APB7_GRP1_FreezePeriph(LL_DBGMCU_APB7_GRP1_RTC_STOP);
|
||||||
|
LL_DBGMCU_APB7_GRP1_FreezePeriph(LL_DBGMCU_APB7_GRP1_LPTIM1_STOP);
|
||||||
|
#else
|
||||||
|
LL_DBGMCU_DisableDBGStandbyMode();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Enabling Ultra Low power mode */
|
||||||
LL_PWR_EnableUltraLowPowerMode();
|
LL_PWR_EnableUltraLowPowerMode();
|
||||||
|
|
||||||
LL_FLASH_EnableSleepPowerDown();
|
LL_FLASH_EnableSleepPowerDown();
|
||||||
|
|
|
@ -32,7 +32,7 @@ LOG_MODULE_REGISTER(soc);
|
||||||
*
|
*
|
||||||
* @return 0
|
* @return 0
|
||||||
*/
|
*/
|
||||||
static int stm32wba_init(void)
|
int stm32wba_init(void)
|
||||||
{
|
{
|
||||||
/* Enable instruction cache in 1-way (direct mapped cache) */
|
/* Enable instruction cache in 1-way (direct mapped cache) */
|
||||||
LL_ICACHE_SetMode(LL_ICACHE_1WAY);
|
LL_ICACHE_SetMode(LL_ICACHE_1WAY);
|
||||||
|
@ -51,7 +51,6 @@ static int stm32wba_init(void)
|
||||||
LL_PWR_SetRegulatorSupply(LL_PWR_LDO_SUPPLY);
|
LL_PWR_SetRegulatorSupply(LL_PWR_LDO_SUPPLY);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,9 @@
|
||||||
|
|
||||||
#include <stm32wbaxx.h>
|
#include <stm32wbaxx.h>
|
||||||
|
|
||||||
|
/* function exported to the soc power.c */
|
||||||
|
int stm32wba_init(void);
|
||||||
|
|
||||||
#endif /* !_ASMLANGUAGE */
|
#endif /* !_ASMLANGUAGE */
|
||||||
|
|
||||||
#endif /* _STM32WBA_SOC_H_ */
|
#endif /* _STM32WBA_SOC_H_ */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue