stm32: Add STM32H5 support for sleep mode.
Update rtc, machine and powerctrl drivers to support STM32H5 sleep modes. This makes RTC alarm wakeup working from lightsleep() and deepsleep(). Changes: - Determine start reason for machine.reset_cause() in modmachine.c. - Add proper interrupt clear code in rtc.c. - Add wakeup functionality in powerctrl_enter_stop_mode(). Remember and restore voltage scaling level. Restart HSI48 if it was on before entering sleep mode. - Clear DBGMCU_CR in SystemClock_Config() as for other variants. Otherwise debug flags prevent entering sleep mode. Implementation Notes: - rtc.c: EXTI_RTSTR1 bits are not present for H5. Code sequence from G0/G4/L4/WB/WL would be invalid. RTSTR is only defined for external (GPIO) interrupts. Maybe this is also true for other STM32 variants. - powerctrl_enter_stop_mode() uses complicated, nested conditionals to select STM32 variants. To make code slightly better readable, comment have been added. A non-nested, #if/#elif sequence would make the code more readable. I leave this to the original authors. Signed-off-by: Rene Straub <rene@see5.ch>
This commit is contained in:
parent
e5014a4d79
commit
47ea831c0e
|
@ -108,6 +108,12 @@ void machine_init(void) {
|
||||||
reset_cause = PYB_RESET_DEEPSLEEP;
|
reset_cause = PYB_RESET_DEEPSLEEP;
|
||||||
PWR->CR1 |= PWR_CR1_CSBF;
|
PWR->CR1 |= PWR_CR1_CSBF;
|
||||||
} else
|
} else
|
||||||
|
#elif defined(STM32H5)
|
||||||
|
if (PWR->PMSR & PWR_PMSR_STOPF || PWR->PMSR & PWR_PMSR_SBF) {
|
||||||
|
// came out of standby or stop mode
|
||||||
|
reset_cause = PYB_RESET_DEEPSLEEP;
|
||||||
|
PWR->PMCR |= PWR_PMCR_CSSF;
|
||||||
|
} else
|
||||||
#elif defined(STM32H7)
|
#elif defined(STM32H7)
|
||||||
if (PWR->CPUCR & PWR_CPUCR_SBF || PWR->CPUCR & PWR_CPUCR_STOPF) {
|
if (PWR->CPUCR & PWR_CPUCR_SBF || PWR->CPUCR & PWR_CPUCR_STOPF) {
|
||||||
// came out of standby or stop mode
|
// came out of standby or stop mode
|
||||||
|
|
|
@ -48,6 +48,8 @@
|
||||||
#define POWERCTRL_GET_VOLTAGE_SCALING() PWR_REGULATOR_VOLTAGE_SCALE0
|
#define POWERCTRL_GET_VOLTAGE_SCALING() PWR_REGULATOR_VOLTAGE_SCALE0
|
||||||
#elif defined(STM32H723xx)
|
#elif defined(STM32H723xx)
|
||||||
#define POWERCTRL_GET_VOLTAGE_SCALING() LL_PWR_GetRegulVoltageScaling()
|
#define POWERCTRL_GET_VOLTAGE_SCALING() LL_PWR_GetRegulVoltageScaling()
|
||||||
|
#elif defined(STM32H5)
|
||||||
|
#define POWERCTRL_GET_VOLTAGE_SCALING() LL_PWR_GetRegulVoltageScaling()
|
||||||
#else
|
#else
|
||||||
#define POWERCTRL_GET_VOLTAGE_SCALING() \
|
#define POWERCTRL_GET_VOLTAGE_SCALING() \
|
||||||
(((PWR->CSR1 & PWR_CSR1_ACTVOS) && (SYSCFG->PWRCR & SYSCFG_PWRCR_ODEN)) ? \
|
(((PWR->CSR1 & PWR_CSR1_ACTVOS) && (SYSCFG->PWRCR & SYSCFG_PWRCR_ODEN)) ? \
|
||||||
|
@ -797,6 +799,14 @@ void powerctrl_enter_stop_mode(void) {
|
||||||
HAL_PWREx_EnableFlashPowerDown();
|
HAL_PWREx_EnableFlashPowerDown();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(STM32H5)
|
||||||
|
// Save RCC CR to re-enable OSCs and PLLs after wake up from low power mode.
|
||||||
|
uint32_t rcc_cr = RCC->CR;
|
||||||
|
|
||||||
|
// Save the current voltage scaling level to restore after exiting low power mode.
|
||||||
|
uint32_t vscaling = POWERCTRL_GET_VOLTAGE_SCALING();
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(STM32H7)
|
#if defined(STM32H7)
|
||||||
// Save RCC CR to re-enable OSCs and PLLs after wake up from low power mode.
|
// Save RCC CR to re-enable OSCs and PLLs after wake up from low power mode.
|
||||||
uint32_t rcc_cr = RCC->CR;
|
uint32_t rcc_cr = RCC->CR;
|
||||||
|
@ -837,9 +847,9 @@ void powerctrl_enter_stop_mode(void) {
|
||||||
while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_HSI48) {
|
while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_HSI48) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else // defined(STM32F0)
|
||||||
|
|
||||||
#if defined(STM32H7)
|
#if defined(STM32H5) || defined(STM32H7)
|
||||||
// When exiting from Stop or Standby modes, the Run mode voltage scaling is reset to
|
// When exiting from Stop or Standby modes, the Run mode voltage scaling is reset to
|
||||||
// the default VOS3 value. Restore the voltage scaling to the previous voltage scale.
|
// the default VOS3 value. Restore the voltage scaling to the previous voltage scale.
|
||||||
if (vscaling != POWERCTRL_GET_VOLTAGE_SCALING()) {
|
if (vscaling != POWERCTRL_GET_VOLTAGE_SCALING()) {
|
||||||
|
@ -879,7 +889,7 @@ void powerctrl_enter_stop_mode(void) {
|
||||||
while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL1) {
|
while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL1) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else // defined(STM32H5)
|
||||||
|
|
||||||
// enable PLL
|
// enable PLL
|
||||||
__HAL_RCC_PLL_ENABLE();
|
__HAL_RCC_PLL_ENABLE();
|
||||||
|
@ -899,7 +909,7 @@ void powerctrl_enter_stop_mode(void) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif // defined(STM32H5)
|
||||||
|
|
||||||
powerctrl_disable_hsi_if_unused();
|
powerctrl_disable_hsi_if_unused();
|
||||||
|
|
||||||
|
@ -912,6 +922,15 @@ void powerctrl_enter_stop_mode(void) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(STM32H5)
|
||||||
|
if (rcc_cr & RCC_CR_HSI48ON) {
|
||||||
|
// Enable HSI48.
|
||||||
|
LL_RCC_HSI48_Enable();
|
||||||
|
while (!LL_RCC_HSI48_IsReady()) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(STM32H7)
|
#if defined(STM32H7)
|
||||||
// Enable HSI
|
// Enable HSI
|
||||||
if (rcc_cr & RCC_CR_HSION) {
|
if (rcc_cr & RCC_CR_HSION) {
|
||||||
|
|
|
@ -298,6 +298,10 @@ void SystemClock_Config(void) {
|
||||||
LL_RCC_SetUSBClockSource(LL_RCC_USB_CLKSOURCE_PLL3Q);
|
LL_RCC_SetUSBClockSource(LL_RCC_USB_CLKSOURCE_PLL3Q);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef NDEBUG
|
||||||
|
DBGMCU->CR = 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(STM32L0)
|
#elif defined(STM32L0)
|
||||||
|
|
|
@ -756,9 +756,11 @@ mp_obj_t pyb_rtc_wakeup(size_t n_args, const mp_obj_t *args) {
|
||||||
RTC->WPR = 0xff;
|
RTC->WPR = 0xff;
|
||||||
|
|
||||||
// enable external interrupts on line EXTI_RTC_WAKEUP
|
// enable external interrupts on line EXTI_RTC_WAKEUP
|
||||||
#if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL)
|
#if defined(STM32G0) || defined(STM32G4) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL)
|
||||||
EXTI->IMR1 |= 1 << EXTI_RTC_WAKEUP;
|
EXTI->IMR1 |= 1 << EXTI_RTC_WAKEUP;
|
||||||
EXTI->RTSR1 |= 1 << EXTI_RTC_WAKEUP;
|
EXTI->RTSR1 |= 1 << EXTI_RTC_WAKEUP;
|
||||||
|
#elif defined(STM32H5)
|
||||||
|
EXTI->IMR1 |= 1 << EXTI_RTC_WAKEUP;
|
||||||
#elif defined(STM32H7)
|
#elif defined(STM32H7)
|
||||||
EXTI_D1->IMR1 |= 1 << EXTI_RTC_WAKEUP;
|
EXTI_D1->IMR1 |= 1 << EXTI_RTC_WAKEUP;
|
||||||
EXTI->RTSR1 |= 1 << EXTI_RTC_WAKEUP;
|
EXTI->RTSR1 |= 1 << EXTI_RTC_WAKEUP;
|
||||||
|
@ -768,8 +770,10 @@ mp_obj_t pyb_rtc_wakeup(size_t n_args, const mp_obj_t *args) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// clear interrupt flags
|
// clear interrupt flags
|
||||||
#if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32WL)
|
#if defined(STM32G0) || defined(STM32G4) || defined(STM32WL)
|
||||||
RTC->ICSR &= ~RTC_ICSR_WUTWF;
|
RTC->ICSR &= ~RTC_ICSR_WUTWF;
|
||||||
|
#elif defined(STM32H5)
|
||||||
|
RTC->SCR = RTC_SCR_CWUTF;
|
||||||
#elif defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || defined(STM32H7B3xx) || defined(STM32H7B3xxQ)
|
#elif defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || defined(STM32H7B3xx) || defined(STM32H7B3xxQ)
|
||||||
RTC->SR &= ~RTC_SR_WUTF;
|
RTC->SR &= ~RTC_SR_WUTF;
|
||||||
#else
|
#else
|
||||||
|
|
Loading…
Reference in New Issue