cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L4 Wakeup source never detectable after power cycle

Maximilian Pohl
Associate II

Hello everybody,

i am having trouble determining the wakeup source after power cycling and i can not figure out why this is.

Simple test case:

I am using the NUCLEO-L496ZG->Examples->PWR->PWR_SHUTDOWN example as a base.

The example was slightly modified to produce serial output of the pwr status register and "out of shutdown" information.

int main(void)
{
  HAL_Init();
 
  /* Configure the system clock to 80 MHz */
  SystemClock_Config();
 
    /* Enable Power Clock */
  __HAL_RCC_PWR_CLK_ENABLE(); 
  HAL_PWR_EnableBkUpAccess();
 
  /* Read PWR status register to determine wakeup source */
  printf("PWR->SR1: 0x%08X\n", PWR->SR1);
  printf("PWR->SR2: 0x%08X\n", PWR->SR2);
  
  /* Check if the system was resumed from shutdown mode,
     resort to RTC back-up register RTC_BKP31R to verify 
     whether or not shutdown entry flag was set by software
     before entering shutdown mode.  */
  if (READ_REG(RTC->BKP31R) == 1)
  {
     WRITE_REG( RTC->BKP31R, 0x0 );  /* reset back-up register */
     printf("OUT OF SHUTDOWN\n");
  }
 
    /* Insert 5 seconds delay */
    HAL_Delay(5000);
  
    /* Disable all used wakeup sources: WKUP pin */
    HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN3);
    
    /* Clear wake up Flag */
    __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WUF3);
    
    /* Enable wakeup pin WKUP2 */
    HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN3_HIGH);
    
    /* Set RTC back-up register RTC_BKP31R to indicate
       later on that system has entered shutdown mode  */    
    WRITE_REG( RTC->BKP31R, 0x1 ); 
 
    /* Read PWR status register to see if wakeup source was reset */
    printf("PWR->SR1: 0x%08X\n", PWR->SR1);
    printf("PWR->SR2: 0x%08X\n", PWR->SR2);
    
    /* Enter shutdown mode */
    HAL_PWREx_EnterSHUTDOWNMode();
  
  while (1)
  {
  }
}

The behavior i experience:

Flash the device -> Run:

Produces:

PWR->SR1: 0x00000000
PWR->SR2: 0x00000100
 
PWR->SR1: 0x00000000
PWR->SR2: 0x00000100

Which has to be expected since the wakeup pin was just configured before shutting down.

Trigger wakeup pin 3 -> RUN:

Produces:

PWR->SR1: 0x00000104
PWR->SR2: 0x00000100
OUT OF SHUTDOWN
PWR->SR1: 0x00000100
PWR->SR2: 0x00000100

Which also gives the expected result. PWR->SR1 WUF3 is set and gets reset after pin configuration. Out of shutdown is detected also correctly.

Now assume the device looses power (i simply disconnect it from its power source for a few seconds).

Power device -> RUN:

Produces:

PWR->SR1: 0x00000000
PWR->SR2: 0x00000100
OUT OF SHUTDOWN
PWR->SR1: 0x00000000
PWR->SR2: 0x00000100

Still as i would expect. No external wakeup and PWR->SR1 SBF cleared by the power reset.

Again Trigger wakeup pin 3 -> RUN:

Produces:

PWR->SR1: 0x00000000
PWR->SR2: 0x00000100
OUT OF SHUTDOWN
PWR->SR1: 0x00000000
PWR->SR2: 0x00000100

The same output as directly after the power reset but from shutdown. Here i would expect the output generated earlier with PWR->SR1 SBF and WUF3 flags set.

I wonder if i must clear or reset any registers after power reset? It is not clear to me if i manually need to reset PWR->SCR CSBF since it seems related to the behavior?

Any guidance to the appropriate resource or explanation of this behavor would be highly appreciated.

Best Regards

8 REPLIES 8
Maximilian Pohl
Associate II

Quick update after i explored the issue somewhat further.

After power reset the flags in the rcc control/status register are set to indicate the reset source.

I found no validation for this assumption, but in case they must be cleared before beeing able to read the pwr register i simply reset it like:

int main(void)
{   
    [...]    
 
    HAL_PWR_EnableBkUpAccess();
 
    __HAL_RCC_CLEAR_RESET_FLAGS();
     
    /* Read PWR status register to determine wakeup source */
    printf("PWR->SR1: 0x%08X\n", PWR->SR1);
    printf("PWR->SR2: 0x%08X\n", PWR->SR2);
      
    [...]
     
     /* Read PWR status register to see if wakeup source was reset */
     printf("PWR->SR1: 0x%08X\n", PWR->SR1);
     printf("PWR->SR2: 0x%08X\n", PWR->SR2);
        
      /* Enter shutdown mode */
      HAL_PWREx_EnterSHUTDOWNMode();
      
    while (1)
    {
    }
}

This did not seem to make any difference, unfortunately.

Fom an errate sheet i got the information that:

2.3.9 PWR_CR4 register write access may not be completed if a Low-power mode is entered just after the write operation Description

PWR_CR4 write access should insert three APB1 wait states, but it does not. Consequently, if a low-power mode is entered just after writing into this register, the PWR_CR4 register may not be updated before the low-power mode is entered. This can occur in particular when the APB1 clock is prescaled.

Workaround

PWR_CR4 register must be read after the write operation to ensure that the write is done before entering the low-power mode.

So i read back the PWR->CR3 and PWR->CR4, after enabling the wakeup pin to make sure they are set correctly.

int main(void)
{         
    [...]
    
    /* Disable all used wakeup sources: WKUP pin */
    HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN2);
    /* Clear wake up Flag */
    __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WUF2);
    /* Enable wakeup pin WKUP2 */
    HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN2_HIGH);
    
    printf("PWR->CR3: 0x%08X\n", PWR->CR3);
    printf("PWR->CR4: 0x%08X\n", PWR->CR4);
    
    /* Read PWR status register to see if wakeup source was reset */
    printf("PWR->SR1: 0x%08X\n", PWR->SR1);
    printf("PWR->SR2: 0x%08X\n", PWR->SR2);
        
    /* Enter shutdown mode */
    HAL_PWREx_EnterSHUTDOWNMode();
      
    while (1)
    {
    }
}

This shows that the registers are set as expected.

Just to be absolutely sure i implemented the wakeup pin configuration, using the equivalent ATOMIC_ bit and register operations.

Unfortunately this did not change the behavior either.

Sarra.S
ST Employee

Hello @Maximilian Pohl​ and thank you for your detailed explanation :smiling_face_with_smiling_eyes:,

first, I don't think that PWR->SR2 in useful to monitor! Instead, it is useful to see the RTC->BKP31R register to know whether you are in Shutdown mode or not:

printf("PWR->SR1: 0x%08X\n", PWR->SR1);

printf("PWR->SR2: 0x%08X\n", PWR->SR2);

printf("RTC->BKP31R: 0x%08X\n", RTC->BKP31R);

regarding the PWR->SR1 register, as it is mentioned in RM0351, and as you likely know, the Standby flag SBF is cleared by setting the CSBF bit in the PWR_SCR register.

Have you tried it yet ?

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Hello @Sarra.S​,

you are right about monitoring PWR->SR2 not really serving any purpose.

Is the rtc backup register a reliable way to check if the system enters shutdown?

As i understand the example this is just set if the example runs to completion and reset after wakeup until it gets set again?

But this is a register we as users write manually and will not be touched by hardware to indicate shutdown - or any standby mode - was entered, right?

Of course i still tried the same test routine as before. Please see below output

/* Flash -> Run */
PWR->SR1: 0x00000000
RTC->BKP31R: 0x00000000
 
PWR->SR1: 0x00000000
RTC->BKP31R: 0x00000001
 
/* Trigger wakeup pin 3 -> run */
PWR->SR1: 0x00000104
RTC->BKP31R: 0x00000001
OUT OF SHUTDOWN
PWR->SR1: 0x00000000
RTC->BKP31R: 0x00000001
 
/* Disconnect power -> power up -> run */
PWR->SR1: 0x00000000
RTC->BKP31R: 0x00000001
OUT OF SHUTDOWN
PWR->SR1: 0x00000000
RTC->BKP31R: 0x00000001
 
/* Again trigger wakeup pin 3 -> run */
PWR->SR1: 0x00000000
RTC->BKP31R: 0x00000001
OUT OF SHUTDOWN
PWR->SR1: 0x00000000
RTC->BKP31R: 0x00000001

Regarding PWR_SCR SBF bit i understand it is set by hardware when entering a standby mode. It gets set in this example as expected.

I do not know if we have to clear it after it is set - i tried anyway, but it does not change the behavior.

After a power cycle entering the shutdown mode does not set the SBF anymore.

Maximilian Pohl
Associate II

Essentially i am just trying to learn about the behaviour of the shutdown mode.

I am unable to locate explicit descriptions of the intended functionality of it and experience behavior that seems odd, to me.

There are multiple threads describing the same - or very similar - issues.

Here users discussed they perceive simmilar behavior and are not entirely able to explain it, since there seems to be documentation contradicting the observed behavior.

https://community.st.com/s/question/0D50X0000CEqurVSQR/stm32l476-wakeup-flag-not-set-when-exit-from-shutdown-after-jlink-removed

Here a user describes how they potentially fixed this/a related issue.

https://community.st.com/s/question/0D53W00001bnh8dSAA/how-to-enter-standby-or-shutdown-mode-on-stm32

I am not sure if it boils down to me - and other users - not correctly understanding the use case and expected behavior. At least i can speak for me this may very well be the case. I would greatly appreciating confirmation of this.

@Sarra.S​ Do you have any inside into this topic? It seems i am not the first person wondering about it. Is there any more explicit documentation explaining the observed behavior?

Sarra.S
ST Employee

Hello again @Maximilian Pohl​ 

I'm further investigating in this issue inside ST, I'll keep keep you updated

Thank you!

Sarra

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Was there any solution to this, because I'm having the exact same problem where after losing power, the device will wake up from shutdown. However, it registers as a reset event, and not a wake up event from a button.

Did you ever find out the reason why, or find a solution?

ouss_mans
Associate II

Hello,

Did you find a solution for this issue, please?