summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ports/stm32/modmachine.c120
-rw-r--r--ports/stm32/powerctrl.c125
-rw-r--r--ports/stm32/powerctrl.h2
3 files changed, 130 insertions, 117 deletions
diff --git a/ports/stm32/modmachine.c b/ports/stm32/modmachine.c
index e0d9afbb5..26eb99296 100644
--- a/ports/stm32/modmachine.c
+++ b/ports/stm32/modmachine.c
@@ -324,131 +324,17 @@ STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) {
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_freq_obj, 0, 4, machine_freq);
STATIC mp_obj_t machine_sleep(void) {
- #if defined(STM32L4)
- // Configure the MSI as the clock source after waking up
- __HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_MSI);
- #endif
-
- #if !defined(STM32F0) && !defined(STM32L4)
- // takes longer to wake but reduces stop current
- HAL_PWREx_EnableFlashPowerDown();
- #endif
-
- # if defined(STM32F7)
- HAL_PWR_EnterSTOPMode((PWR_CR1_LPDS | PWR_CR1_LPUDS | PWR_CR1_FPDS | PWR_CR1_UDEN), PWR_STOPENTRY_WFI);
- # else
- HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
- #endif
-
- // reconfigure the system clock after waking up
-
- #if defined(STM32F0)
-
- // Enable HSI48
- __HAL_RCC_HSI48_ENABLE();
- while (!__HAL_RCC_GET_FLAG(RCC_FLAG_HSI48RDY)) {
- }
-
- // Select HSI48 as system clock source
- MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_SYSCLKSOURCE_HSI48);
- while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_HSI48) {
- }
-
- #else
-
- #if !defined(STM32L4)
- // enable HSE
- __HAL_RCC_HSE_CONFIG(MICROPY_HW_CLK_HSE_STATE);
- while (!__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY)) {
- }
- #endif
-
- // enable PLL
- __HAL_RCC_PLL_ENABLE();
- while (!__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY)) {
- }
-
- // select PLL as system clock source
- MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_SYSCLKSOURCE_PLLCLK);
- #if defined(STM32H7)
- while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL1) {
- #else
- while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL) {
- #endif
- }
-
- #if defined(STM32F7)
- if (RCC->DCKCFGR2 & RCC_DCKCFGR2_CK48MSEL) {
- // Enable PLLSAI if it is selected as 48MHz source
- RCC->CR |= RCC_CR_PLLSAION;
- while (!(RCC->CR & RCC_CR_PLLSAIRDY)) {
- }
- }
- #endif
-
- #if defined(STM32L4)
- // Enable PLLSAI1 for peripherals that use it
- RCC->CR |= RCC_CR_PLLSAI1ON;
- while (!(RCC->CR & RCC_CR_PLLSAI1RDY)) {
- }
- #endif
-
- #endif
-
+ powerctrl_enter_stop_mode();
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_0(machine_sleep_obj, machine_sleep);
STATIC mp_obj_t machine_deepsleep(void) {
- rtc_init_finalise();
-
-#if defined(STM32L4)
+ #if defined(STM32L4)
printf("machine.deepsleep not supported yet\n");
-#else
- // We need to clear the PWR wake-up-flag before entering standby, since
- // the flag may have been set by a previous wake-up event. Furthermore,
- // we need to disable the wake-up sources while clearing this flag, so
- // that if a source is active it does actually wake the device.
- // See section 5.3.7 of RM0090.
-
- // Note: we only support RTC ALRA, ALRB, WUT and TS.
- // TODO support TAMP and WKUP (PA0 external pin).
- #if defined(STM32F0)
- #define CR_BITS (RTC_CR_ALRAIE | RTC_CR_WUTIE | RTC_CR_TSIE)
- #define ISR_BITS (RTC_ISR_ALRAF | RTC_ISR_WUTF | RTC_ISR_TSF)
- #else
- #define CR_BITS (RTC_CR_ALRAIE | RTC_CR_ALRBIE | RTC_CR_WUTIE | RTC_CR_TSIE)
- #define ISR_BITS (RTC_ISR_ALRAF | RTC_ISR_ALRBF | RTC_ISR_WUTF | RTC_ISR_TSF)
- #endif
-
- // save RTC interrupts
- uint32_t save_irq_bits = RTC->CR & CR_BITS;
-
- // disable RTC interrupts
- RTC->CR &= ~CR_BITS;
-
- // clear RTC wake-up flags
- RTC->ISR &= ~ISR_BITS;
-
- #if defined(STM32F7)
- // disable wake-up flags
- PWR->CSR2 &= ~(PWR_CSR2_EWUP6 | PWR_CSR2_EWUP5 | PWR_CSR2_EWUP4 | PWR_CSR2_EWUP3 | PWR_CSR2_EWUP2 | PWR_CSR2_EWUP1);
- // clear global wake-up flag
- PWR->CR2 |= PWR_CR2_CWUPF6 | PWR_CR2_CWUPF5 | PWR_CR2_CWUPF4 | PWR_CR2_CWUPF3 | PWR_CR2_CWUPF2 | PWR_CR2_CWUPF1;
- #elif defined(STM32H7)
- // TODO
#else
- // clear global wake-up flag
- PWR->CR |= PWR_CR_CWUF;
+ powerctrl_enter_standby_mode();
#endif
-
- // enable previously-enabled RTC interrupts
- RTC->CR |= save_irq_bits;
-
- // enter standby mode
- HAL_PWR_EnterSTANDBYMode();
- // we never return; MCU is reset on exit from standby
-#endif
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_0(machine_deepsleep_obj, machine_deepsleep);
diff --git a/ports/stm32/powerctrl.c b/ports/stm32/powerctrl.c
index 4199cf690..45e886e13 100644
--- a/ports/stm32/powerctrl.c
+++ b/ports/stm32/powerctrl.c
@@ -27,6 +27,7 @@
#include "py/mperrno.h"
#include "py/mphal.h"
#include "powerctrl.h"
+#include "rtc.h"
#include "genhdr/pllfreqtable.h"
#if !defined(STM32F0)
@@ -257,3 +258,127 @@ set_clk:
}
#endif
+
+void powerctrl_enter_stop_mode(void) {
+ #if defined(STM32L4)
+ // Configure the MSI as the clock source after waking up
+ __HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_MSI);
+ #endif
+
+ #if !defined(STM32F0) && !defined(STM32L4)
+ // takes longer to wake but reduces stop current
+ HAL_PWREx_EnableFlashPowerDown();
+ #endif
+
+ # if defined(STM32F7)
+ HAL_PWR_EnterSTOPMode((PWR_CR1_LPDS | PWR_CR1_LPUDS | PWR_CR1_FPDS | PWR_CR1_UDEN), PWR_STOPENTRY_WFI);
+ # else
+ HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
+ #endif
+
+ // reconfigure the system clock after waking up
+
+ #if defined(STM32F0)
+
+ // Enable HSI48
+ __HAL_RCC_HSI48_ENABLE();
+ while (!__HAL_RCC_GET_FLAG(RCC_FLAG_HSI48RDY)) {
+ }
+
+ // Select HSI48 as system clock source
+ MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_SYSCLKSOURCE_HSI48);
+ while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_HSI48) {
+ }
+
+ #else
+
+ #if !defined(STM32L4)
+ // enable HSE
+ __HAL_RCC_HSE_CONFIG(MICROPY_HW_CLK_HSE_STATE);
+ while (!__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY)) {
+ }
+ #endif
+
+ // enable PLL
+ __HAL_RCC_PLL_ENABLE();
+ while (!__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY)) {
+ }
+
+ // select PLL as system clock source
+ MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_SYSCLKSOURCE_PLLCLK);
+ #if defined(STM32H7)
+ while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL1) {
+ }
+ #else
+ while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL) {
+ }
+ #endif
+
+ #if defined(STM32F7)
+ if (RCC->DCKCFGR2 & RCC_DCKCFGR2_CK48MSEL) {
+ // Enable PLLSAI if it is selected as 48MHz source
+ RCC->CR |= RCC_CR_PLLSAION;
+ while (!(RCC->CR & RCC_CR_PLLSAIRDY)) {
+ }
+ }
+ #endif
+
+ #if defined(STM32L4)
+ // Enable PLLSAI1 for peripherals that use it
+ RCC->CR |= RCC_CR_PLLSAI1ON;
+ while (!(RCC->CR & RCC_CR_PLLSAI1RDY)) {
+ }
+ #endif
+
+ #endif
+}
+
+#if !defined(STM32L4)
+void powerctrl_enter_standby_mode(void) {
+ rtc_init_finalise();
+
+ // We need to clear the PWR wake-up-flag before entering standby, since
+ // the flag may have been set by a previous wake-up event. Furthermore,
+ // we need to disable the wake-up sources while clearing this flag, so
+ // that if a source is active it does actually wake the device.
+ // See section 5.3.7 of RM0090.
+
+ // Note: we only support RTC ALRA, ALRB, WUT and TS.
+ // TODO support TAMP and WKUP (PA0 external pin).
+ #if defined(STM32F0)
+ #define CR_BITS (RTC_CR_ALRAIE | RTC_CR_WUTIE | RTC_CR_TSIE)
+ #define ISR_BITS (RTC_ISR_ALRAF | RTC_ISR_WUTF | RTC_ISR_TSF)
+ #else
+ #define CR_BITS (RTC_CR_ALRAIE | RTC_CR_ALRBIE | RTC_CR_WUTIE | RTC_CR_TSIE)
+ #define ISR_BITS (RTC_ISR_ALRAF | RTC_ISR_ALRBF | RTC_ISR_WUTF | RTC_ISR_TSF)
+ #endif
+
+ // save RTC interrupts
+ uint32_t save_irq_bits = RTC->CR & CR_BITS;
+
+ // disable RTC interrupts
+ RTC->CR &= ~CR_BITS;
+
+ // clear RTC wake-up flags
+ RTC->ISR &= ~ISR_BITS;
+
+ #if defined(STM32F7)
+ // disable wake-up flags
+ PWR->CSR2 &= ~(PWR_CSR2_EWUP6 | PWR_CSR2_EWUP5 | PWR_CSR2_EWUP4 | PWR_CSR2_EWUP3 | PWR_CSR2_EWUP2 | PWR_CSR2_EWUP1);
+ // clear global wake-up flag
+ PWR->CR2 |= PWR_CR2_CWUPF6 | PWR_CR2_CWUPF5 | PWR_CR2_CWUPF4 | PWR_CR2_CWUPF3 | PWR_CR2_CWUPF2 | PWR_CR2_CWUPF1;
+ #elif defined(STM32H7)
+ // TODO
+ #else
+ // clear global wake-up flag
+ PWR->CR |= PWR_CR_CWUF;
+ #endif
+
+ // enable previously-enabled RTC interrupts
+ RTC->CR |= save_irq_bits;
+
+ // enter standby mode
+ HAL_PWR_EnterSTANDBYMode();
+ // we never return; MCU is reset on exit from standby
+}
+#endif
diff --git a/ports/stm32/powerctrl.h b/ports/stm32/powerctrl.h
index b9de324fb..b26cab391 100644
--- a/ports/stm32/powerctrl.h
+++ b/ports/stm32/powerctrl.h
@@ -30,5 +30,7 @@
int powerctrl_rcc_clock_config_pll(RCC_ClkInitTypeDef *rcc_init, uint32_t sysclk_mhz, bool need_pllsai);
int powerctrl_set_sysclk(uint32_t sysclk, uint32_t ahb, uint32_t apb1, uint32_t apb2);
+void powerctrl_enter_stop_mode(void);
+void powerctrl_enter_standby_mode(void);
#endif // MICROPY_INCLUDED_STM32_POWERCTRL_H