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>
pull/12761/head
Rene Straub 2023-10-21 15:03:53 +02:00 zatwierdzone przez Damien George
rodzic e5014a4d79
commit 47ea831c0e
4 zmienionych plików z 39 dodań i 6 usunięć

Wyświetl plik

@ -108,6 +108,12 @@ void machine_init(void) {
reset_cause = PYB_RESET_DEEPSLEEP;
PWR->CR1 |= PWR_CR1_CSBF;
} 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)
if (PWR->CPUCR & PWR_CPUCR_SBF || PWR->CPUCR & PWR_CPUCR_STOPF) {
// came out of standby or stop mode

Wyświetl plik

@ -48,6 +48,8 @@
#define POWERCTRL_GET_VOLTAGE_SCALING() PWR_REGULATOR_VOLTAGE_SCALE0
#elif defined(STM32H723xx)
#define POWERCTRL_GET_VOLTAGE_SCALING() LL_PWR_GetRegulVoltageScaling()
#elif defined(STM32H5)
#define POWERCTRL_GET_VOLTAGE_SCALING() LL_PWR_GetRegulVoltageScaling()
#else
#define POWERCTRL_GET_VOLTAGE_SCALING() \
(((PWR->CSR1 & PWR_CSR1_ACTVOS) && (SYSCFG->PWRCR & SYSCFG_PWRCR_ODEN)) ? \
@ -797,6 +799,14 @@ void powerctrl_enter_stop_mode(void) {
HAL_PWREx_EnableFlashPowerDown();
#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)
// Save RCC CR to re-enable OSCs and PLLs after wake up from low power mode.
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) {
}
#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
// the default VOS3 value. Restore the voltage scaling to the previous voltage scale.
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) {
}
#else
#else // defined(STM32H5)
// enable PLL
__HAL_RCC_PLL_ENABLE();
@ -899,7 +909,7 @@ void powerctrl_enter_stop_mode(void) {
}
#endif
#endif
#endif // defined(STM32H5)
powerctrl_disable_hsi_if_unused();
@ -912,6 +922,15 @@ void powerctrl_enter_stop_mode(void) {
}
#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)
// Enable HSI
if (rcc_cr & RCC_CR_HSION) {

Wyświetl plik

@ -298,6 +298,10 @@ void SystemClock_Config(void) {
LL_RCC_SetUSBClockSource(LL_RCC_USB_CLKSOURCE_PLL3Q);
#endif
#ifdef NDEBUG
DBGMCU->CR = 0;
#endif
}
#elif defined(STM32L0)

Wyświetl plik

@ -756,9 +756,11 @@ mp_obj_t pyb_rtc_wakeup(size_t n_args, const mp_obj_t *args) {
RTC->WPR = 0xff;
// 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->RTSR1 |= 1 << EXTI_RTC_WAKEUP;
#elif defined(STM32H5)
EXTI->IMR1 |= 1 << EXTI_RTC_WAKEUP;
#elif defined(STM32H7)
EXTI_D1->IMR1 |= 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
// clear interrupt flags
#if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32WL)
#if defined(STM32G0) || defined(STM32G4) || defined(STM32WL)
RTC->ICSR &= ~RTC_ICSR_WUTWF;
#elif defined(STM32H5)
RTC->SCR = RTC_SCR_CWUTF;
#elif defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || defined(STM32H7B3xx) || defined(STM32H7B3xxQ)
RTC->SR &= ~RTC_SR_WUTF;
#else