K. Koovalsky
K. Koovalsky

Reputation: 606

STM32 WFI exits immediately after being called

I run FreeRTOS and set up tickless idle. I want to put the STM32L432KC chip into the STOP2 mode but the problem is that WFI instruction exits immediately.

I want to wake up the chip using RTC WAKEUP interrupt.

RTC is initialized like that:

  /* Disable RTC registers write protection */
  LL_RTC_DisableWriteProtection(RTC);

  // Disable wake up timer to modify it.
  LL_RTC_WAKEUP_Disable(RTC);

  // Wait until the registers could get changed.
  while(!LL_RTC_IsActiveFlag_WUTW(RTC))
        ;

  /* Setting the Wakeup time to 60 s */
  LL_RTC_WAKEUP_SetAutoReload(RTC, 60 - 1);

  // CKSPRE has 1Hz frequency.
  LL_RTC_WAKEUP_SetClock(RTC, LL_RTC_WAKEUPCLOCK_CKSPRE);

  /* Enable RTC registers write protection */
  LL_RTC_EnableWriteProtection(RTC);

  LL_EXTI_EnableRisingTrig_0_31(LL_EXTI_LINE_20);
  LL_EXTI_EnableIT_0_31(LL_EXTI_LINE_20);

I skipped the boilerplate initialization code generated by CubeMX.

In FreeRTOSConfig.h I configured the tickless idle to use my post and pre hooks:

#define configUSE_TICKLESS_IDLE                     1

// You must manually convert milliseconds to ticks because pdMS_TO_TICKS won't work here.
#define configEXPECTED_IDLE_TIME_BEFORE_SLEEP       7

extern void pre_sleep(long unsigned int *expected_idle_time); 
#define configPRE_SLEEP_PROCESSING(xExpectedIdleTime) pre_sleep(xExpectedIdleTime)

extern void post_sleep(long unsigned int *expected_idle_time);
#define configPOST_SLEEP_PROCESSING(xExpectedIdleTime) post_sleep(xExpectedIdleTime)

pre_sleep function sets xExpectedIdleTime to 0 to inform that WFI is called explicitly in the pre-hook:

void pre_sleep(long unsigned int *expected_idle_time)
{

    *expected_idle_time = 0;

    enter_sleep_mode(LL_PWR_MODE_STOP2);
}

void post_sleep(long unsigned int *expected_idle_time) { }

Function which enters sleep mode:

void enter_sleep_mode(uint32_t low_power_mode)
  /* ######## ENABLE WUT #################################################*/
  /* Disable RTC registers write protection */
  LL_RTC_DisableWriteProtection(RTC);

  /* Enable wake up counter and wake up interrupt */
  /* Note: Periodic wakeup interrupt should be enabled to exit the device
     from low-power modes.*/
  LL_RTC_WAKEUP_Enable(RTC);
  LL_RTC_EnableIT_WUT(RTC);
  LL_RTC_ClearFlag_WUT(RTC);

  /* Enable RTC registers write protection */
  LL_RTC_EnableWriteProtection(RTC);

  /* ######## ENTER IN SLEEP MODE ######################################*/
  /** Request to enter a sleep mode.
    * Following procedure describe in STM32L4xx Reference Manual
    * See PWR part, section Low-power modes.
    */
  /* Reset Internal Wake up flag */
  LL_RTC_ClearFlag_WUT(RTC);

  /* Check that PWR Internal Wake-up is enabled */
  if (LL_PWR_IsEnabledInternWU() == 0)
  {
    /* Need to enable the Internal Wake-up line */
    LL_PWR_EnableInternWU();
  }

  /* Set the sleep mode */
  LL_PWR_SetPowerMode(low_power_mode);

  /* Set SLEEPDEEP bit of Cortex System Control Register */
  LL_LPM_EnableDeepSleep();

  /* This option is used to ensure that store operations are completed */
#if defined ( __CC_ARM)
  __force_stores();
#endif

  /* Request Wait For Interrupt */
  __WFI();
}

The WAKEUP handler:

void RTC_WKUP_IRQHandler(void)
{
  if(LL_RTC_IsActiveFlag_WUT(RTC))
  {
    LL_RTC_ClearFlag_WUT(RTC);
    LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_20);
    xTaskNotifyFromISR(wakeup_task_handle);
  }
  else
  {
    NVIC_DisableIRQ(RTC_WKUP_IRQn);
  }
}

I inspected NVIC if there are any pending interrupts and could see that ICPR and ISPR registers are all set to zero.

WFI also exits on Debug Entry request but even when I do not debug (I use STLinkV2) it exits immediately.

What have I missed?

Upvotes: 2

Views: 2537

Answers (2)

Tarick Welling
Tarick Welling

Reputation: 3265

You probably didn't stop the SysClk. This clock will generate a interrupt every millisecond and therefore break out of the WFI. Try adding:

   HAL_SuspendTick();
   // WFI 
   HAL_ResumeTick();

Upvotes: 0

K. Koovalsky
K. Koovalsky

Reputation: 606

The problem is that even when the debugger is attached to the board it won't work.

The issue was solved by simply disconnecting the STLink debugger. Even when the debugger was attached but no power supply was connected to the debugger it didn't work too.

Upvotes: 1

Related Questions