AnsweredAssumed Answered

Question regarding implementation of HAL_PWR_EnterSTOPMode() and other low-power routines in F1 HAL

Question asked by cnoviello on May 14, 2016
Latest reply on Jun 1, 2016 by Amel N
Hi,
I'm experiencing a really obscure issue on an STM32F103 using the latest CubeF1 HAL, and I suspect that it's related to the way the WFI instruction is called.

My scenario is a little bit complex. My code runs with FreeRTOS, but under certain conditions I can suspend the tick generation and place the MCU in STOP mode using the HAL_PWR_EnterSTOPMode() with WFI instruction. The EXTI controller is configured so that PC13 is the wake up pin. The problem I've is that when the MCU wakes up, it immediately generates an hardfault, which doesn't give me useful information.

The code works perfectly on other STM32 families (especially F0 and L4). Digging in this issue, I realized that the HAL_PWR_EnterSTOPMode() doesn't follow what ARM says about the right calling sequence of WFI instruction, as stated here: http://infocenter.arm.com/help/topic/com.arm.doc.dai0321a/BIHICBGB.html

So, I've modified the function in this way:

void HAL_PWR_EnterSTOPMode(uint32_t Regulator, uint8_t STOPEntry) {
  /* Check the parameters */
  assert_param(IS_PWR_REGULATOR(Regulator));
  assert_param(IS_PWR_STOP_ENTRY(STOPEntry));
 
  /* Clear PDDS bit in PWR register to specify entering in STOP mode when CPU enter in Deepsleep */
  CLEAR_BIT(PWR->CR,  PWR_CR_PDDS);
 
  /* Select the voltage regulator mode by setting LPDS bit in PWR register according to Regulator parameter value */
  MODIFY_REG(PWR->CR, PWR_CR_LPDS, Regulator);
 
  /* Set SLEEPDEEP bit of Cortex System Control Register */
  SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
 
  /* Select Stop mode entry --------------------------------------------------*/
  if(STOPEntry == PWR_STOPENTRY_WFI)
  {
    /* Request Wait For Interrupt */
    __DSB(); //Added by me
    __WFI();
    __ISB(); //Added by me
  }
  else
  {
    /* Request Wait For Event */
    __SEV();
    PWR_OverloadWfe(); /* WFE redefine locally */
    PWR_OverloadWfe(); /* WFE redefine locally */
  }
  /* Reset SLEEPDEEP bit of Cortex System Control Register */
  CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
}

With this modification, the code works well and the MCU exists from STOP mode correctly. 

Does someone know more about this? Can ST engineers explain why the HAL_PWR_EnterSTOPMode() isn't implemented in the way suggested by ARM?

Thanks

Outcomes