STM32L4: Fix sleep implementation

Correctly detect and handle the low power run mode when entering and exiting sleep mode.

The generic `hal_sleep` implementation tries to exit LPR mode always, resulting in a spin-loop during a critical section (disabled IRQ).
The new approach returns from LPR to Run mode if enabled (LPR bit set), enters sleep, and resets to the original state on wakeup (WFI).
pull/7813/head
Markus Siglreithmaier 2018-08-13 09:21:31 +02:00
parent 2a824a1ceb
commit 97fef1160c
1 changed files with 27 additions and 0 deletions

View File

@ -151,7 +151,34 @@ void hal_sleep(void)
core_util_critical_section_enter();
// Request to enter SLEEP mode
#if TARGET_STM32L4
// State Transitions (see 5.3 Low-power modes, Fig. 13):
// * (opt): Low Power Run (LPR) Mode -> Run Mode
// * Run Mode -> Sleep
// --- Wait for Interrupt --
// * Sleep -> Run Mode
// * (opt): Run Mode -> Low Power Run Mode
// [5.4.1 Power control register 1 (PWR_CR1)]
// LPR: When this bit is set, the regulator is switched from main mode (MR) to low-power mode (LPR).
int lowPowerMode = PWR->CR1 & PWR_CR1_LPR;
// LPR -> Run
if (lowPowerMode) {
HAL_PWREx_DisableLowPowerRunMode();
}
// Entering Sleep mode [5.3.4 Sleep mode]
CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk)); // SLEEPDEEP = 0
__WFI();
// Run -> LPR
if (lowPowerMode) {
HAL_PWREx_EnableLowPowerRunMode();
}
#else
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
#endif
// Enable IRQs
core_util_critical_section_exit();