Skip to content

Commit

Permalink
soc: arm: stm32wl: Reinit select peripherals on STOP2 exit
Browse files Browse the repository at this point in the history
Reinitialize the following peripherals with recently added reinit logic
upon exiting STOP2 power state: ADC, I2C, SPI, and USART.

These peripherals lose clock context and register contents when the SoC
enters STOP2 mode, and don't operate correctly when it reenters RUN mode
without individual peripheral reinitialization.

closes: zephyrproject-rtos#37352 zephyrproject-rtos#37414 zephyrproject-rtos#59194

Signed-off-by: Kenneth J. Miller <ken@miller.ec>
  • Loading branch information
knthm committed Jun 13, 2023
1 parent e712706 commit 51278cf
Showing 1 changed file with 27 additions and 3 deletions.
30 changes: 27 additions & 3 deletions soc/arm/st_stm32/stm32wl/power.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,23 @@
#include <zephyr/logging/log.h>
LOG_MODULE_DECLARE(soc, CONFIG_SOC_LOG_LEVEL);

#include <adc/adc_stm32.h>
#include <i2c/i2c_ll_stm32.h>
#include <spi/spi_ll_stm32.h>
#include <serial/uart_stm32.h>

/* select MSI as wake-up system clock if configured, HSI otherwise */
#if STM32_SYSCLK_SRC_MSI
#define RCC_STOP_WAKEUPCLOCK_SELECTED LL_RCC_STOP_WAKEUPCLOCK_MSI
#else
#define RCC_STOP_WAKEUPCLOCK_SELECTED LL_RCC_STOP_WAKEUPCLOCK_HSI
#endif

#define STM32_ADC_REINIT(node_id) adc_stm32_reinit(DEVICE_DT_GET(node_id))
#define STM32_I2C_REINIT(node_id) i2c_stm32_reinit(DEVICE_DT_GET(node_id))
#define STM32_SPI_REINIT(node_id) spi_stm32_reinit(DEVICE_DT_GET(node_id))
#define STM32_USART_REINIT(node_id) uart_stm32_reinit(DEVICE_DT_GET(node_id))

/* Invoke Low Power/System Off specific Tasks */
__weak void pm_state_set(enum pm_state state, uint8_t substate_id)
{
Expand Down Expand Up @@ -76,20 +86,34 @@ __weak void pm_state_set(enum pm_state state, uint8_t substate_id)
/* Handle SOC specific activity after Low Power Mode Exit */
__weak void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id)
{
ARG_UNUSED(substate_id);

switch (state) {
case PM_STATE_SUSPEND_TO_IDLE:
LL_LPM_DisableSleepOnExit();
LL_LPM_EnableSleep();
switch (substate_id) {
case 1: /* STOP0 */
break;
case 2: /* STOP1 */
break;
case 3: /* STOP2 */
/* Reinitialize peripheral functionality */
DT_FOREACH_STATUS_OKAY(st_stm32_adc, STM32_ADC_REINIT);
DT_FOREACH_STATUS_OKAY(st_stm32_i2c_v2, STM32_I2C_REINIT);
DT_FOREACH_STATUS_OKAY(st_stm32_spi, STM32_SPI_REINIT);
DT_FOREACH_STATUS_OKAY(st_stm32_usart, STM32_USART_REINIT);
break;
default:
LOG_DBG("Unsupported power substate-id %u", substate_id);
break;
}
/* need to restore the clock */
stm32_clock_control_init(NULL);
break;
case PM_STATE_SOFT_OFF:
/* Nothing to do. */
break;
default:
LOG_DBG("Unsupported power substate-id %u", state);
LOG_DBG("Unsupported power state %u", state);
break;
}

Expand Down

0 comments on commit 51278cf

Please sign in to comment.