cancel
Showing results for 
Search instead for 
Did you mean: 

Wakeup from RTC or GPIO not working from Standby

DHepp.1
Associate

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();

3 REPLIES 3
MM..1
Chief II

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...

> You dont show how you use standby

The last block of authors code shows exactly that. Yes, so few lines compared to a bloatware...

@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.