2021-03-05 06:21 PM
I'm attempting to put my STM32L4xx into Standby mode, and then wake it up from GPIO or RTC. I'm not using any drivers. I've narrowed my problem down to the PWR peripheral clock, although I'm not sure if that is directly the cause.
If PWR clock is on when I call WFI, then it does not actually go to low power mode, and the GPIO does not return it from WFI. However it does pause until the RTC returns it from WFI, it just does not appear to go to a low power state.
If PWR clock is off (if I disable it after setting up the RTC, as shown in the code below), then the device appears to be asleep and the GPIO will wake it up, but the RTC does not.
Here is my clock set up code:
SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_PWREN); // enable PWR clock
asm("NOP");
asm("NOP");
// Configure the RTC
SET_BIT(PWR->CR1, PWR_CR1_DBP);
if ((uint32_t)(READ_BIT(RCC->BDCR, RCC_BDCR_RTCSEL)) != RCC_BDCR_RTCSEL_1) {
SET_BIT(RCC->BDCR, RCC_BDCR_BDRST); // reset the backup domain
CLEAR_BIT(RCC->BDCR, RCC_BDCR_BDRST);
MODIFY_REG(RCC->BDCR, RCC_BDCR_RTCSEL, RCC_BDCR_RTCSEL_1); // use LSI clock
}
SET_BIT(RCC->BDCR, RCC_BDCR_RTCEN); // enable RTC
CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_PWREN); // disable PWR clock
If I remove the last line, which disables the PWR clock, then the RTC does cause an interrupt which returns from WFI(), but the MCU is not actually in low power mode while it is in WFI state. Additionally, the GPIO does not work to wake it up.
In case it is relevant, here is the RTC setup code. I can also share other code, such as GPIO interrupt setup if that would be useful.
/* SETUP RTC TIMER WAKEUP */
SET_BIT(RCC->BDCR, RCC_BDCR_RTCEN);
/* RTC interrupt Init */
NVIC_SetPriority(RTC_WKUP_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
NVIC_EnableIRQ(RTC_WKUP_IRQn);
WRITE_REG(RTC->WPR, RTC_WRITE_PROTECTION_ENABLE_1); // disable write protection for RTC registers
WRITE_REG(RTC->WPR, RTC_WRITE_PROTECTION_ENABLE_2);
// select wakeup alarm, enable wakeup interrupt, enable wakeup alarm, and select the slow 1 hz clock
CLEAR_BIT(RTC->CR, RTC_CR_WUTE); // disable wakeup so we can write to registers
while((RTC->ISR & RTC_ISR_WUTWF) == 0) {
asm("nop"); // wait until WUCKSEL write allowed
}
SET_BIT(RTC->CR, RTC_CR_OSEL_1); //
SET_BIT(RTC->CR, RTC_CR_WUTIE); //wakeup time interrupt enable
SET_BIT(RTC->CR, RTC_CR_WUCKSEL_2); // select 1 hz clock for wakeup clock
WRITE_REG(RTC->WUTR, PWR_WAKEUP_TIMER);
SET_BIT(RTC->CR, RTC_CR_WUTE); //wakeup timer enable
And the code used to go to sleep:
PWR->CR1 |= PWR_CR1_LPMS_STANDBY;
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; // enable deep sleep mode
PWR->SR1 |= PWR_SR1_WUF1 | PWR_SR1_WUF2 | PWR_SR1_WUF3 | PWR_SR1_WUF4 | PWR_SR1_WUF5;
__WFI();
2021-03-06 04:01 AM
You dont show how you use standby , for example
/* Disable all used wakeup sources: PWR_WAKEUP_PIN2 */
HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN2);
/* Clear all related wakeup flags*/
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
/* Enable WakeUp Pin PWR_WAKEUP_PIN2 connected to PC.00 */
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN2);
/* Enter the Standby mode */
HAL_PWR_EnterSTANDBYMode();
/* This code will never be reached! */
while (1)
{
}
this is HAL code and on end comment this code never be reached is real, because mcu is reset. And wakeup is possile only with desired pins not all gpio...
2021-03-06 06:53 AM
> You dont show how you use standby
The last block of authors code shows exactly that. Yes, so few lines compared to a bloatware...
2021-03-07 06:27 AM
@Piranha authors code explain entering standby, but not usage, and too up this code author writes "go to sleep", what is very different mode...
@DHepp.1 ARM cortex have in some situation defined order for work with registers, that your code need respect. Im not expert for L4 , but i accept , that HAL "bloatware" known this condition better as i.