cancel
Showing results for 
Search instead for 
Did you mean: 

WFI usage with RTOS

A3
Associate III

Hi,

I am using STM32F779NI and CMSIS RTOS2 for my project. Software was working well till I added code for low power mode with RTOS tick-less operation as per the link

https://www.keil.com/pack/doc/CMSIS/RTOS2/html/group__CMSIS__RTOS__KernelCtrl.html#gae26683e1606ec633354a2876c68f0c1f and

https://www.keil.com/support/docs/3591.htm

After adding the code in osRtxIdleThread, the soft Timer seems to behave incorrectly. Attaching the respective code snippet.

Software Architecture overview:

After system is turned ON, few tasks are created and a periodic soft timer of 500 ms is created. All tasks are blocking till they get a message in their message queue. The message can be posted from other tasks or via soft timer call backs that is used heavily in our architecture.

Once all the tasks and 500ms Timer are created, then a 6ms periodic timer is created. In the callback of this 6ms Timer, message is posted in one of the high priority task's message queue. With this message reception, this task performs important activities like sensor sampling/polling data etc. every 6ms.

Note: Soft Timer task priority is higher than this task i.e. Timer task priority is osPriorityHigh and this task's priority is osPriorityAboveNormal4.

Also, here a periodic soft timer of 300 ms is created which is for used for a short time of around 20 sec with frequency 300ms. Then it is deleted.

Problem Statement:

The soft timers looks to be signalled more than the required after oskernelResume().

I have printed HAL_GetTick() in the callback of 6ms Timer and 500ms Timer. Note that HAL_GetTick() returns osKernelGetTickCount().

The problem is when I see the printed tick value, consecutive values are 6ms difference apart that is correct, but the value is not as per the real-time.

For a 27 sec log value taken, tick value printed should be around 27000 ms but it went up to 74225 ms. Same behavior for 500ms timer as well.

Note: Both 6ms Timer and 500ms Timer will always run till system is turned Off. I understand oskernelResume compensate for OS tick and timer tick, but with value printed looks like it is over compensating, maybe it is signalled more times. What could be the reason for this?

Any thing to consider for ISR and thread, timer callback execution when using osKernelSuspend, osKernelResume with WFI?

Note: RTC auto wakeup is configured in interrupt for CPU wakeup.

Adding code snippets below.

3 REPLIES 3
A3
Associate III
void osRtxIdleThread (void *argument)
{
    (void)argument;
    static uint32_t intervalStartTimeStamp = 0;
    static uint32_t loopCount = 0;
    #if LOW_POWER_MODE
    uint32_t sleep = 0;
    #endif
    
    while (1)
    {        
        #if LOW_POWER_MODE
        sleep = osKernelSuspend();          /* Suspend RTX thread scheduler */
        //UartPuts ("LPS %d\r\n", sleep);
        
        if (sleep)                      
        {                               
            /* How long can we sleep? */
            /* "sleep" is in RTX Timer Ticks
               which is 1ms in this configuration */
            /* Setup wake-up */
            rtc_ConfigWakeupTime(sleep);
            /* Request to enter SLEEP mode */
            HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
            /* Get Actual Slept time */
            sleep = HAL_RTCEx_GetWakeUpTimer(&RtcHandle);
            sleep = roundFloatToUint32(sleep * RTC_WAKEUP_TIMEBASE);
        }
        osKernelResume(sleep);          /* Resume thread scheduler */
        #endif
    }
}
 
#if LOW_POWER_MODE
void rtc_ConfigWakeupTime(uint32_t sleep)
{
    uint16_t wakeUpCounter = 0x0000;
    /* Disable all used wakeup sources*/
    HAL_RTCEx_DeactivateWakeUpTimer(&RtcHandle);
  
    /* Clear all related wakeup flags */
    __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
  
    /* ## Setting the Wake up time ############################################*/
    /* RTC Wakeup Interrupt Generation: 
    The wake-up counter is set as per the passed value of sleep.
    This value is in terms of ticks which in our case is 1 tick = 1 ms.
    When RTC_WAKEUPCLOCK_RTCCLK_DIV = RTCCLK_Div2 = 2
 
    Wakeup Time Base = (RTC_WAKEUPCLOCK_RTCCLK_DIV /(LSE))
    Wakeup Time Base = (2 /(32768)) = 61.035 us = 0.061 ms
    Wakeup Time = Wakeup Time Base * WakeUpCounter 
      ==> WakeUpCounter = Wakeup Time / Wakeup Time Base
  
    E.g. If sleep time is 6 ms,
    To configure the wake up timer to 6ms the WakeUpCounter is set to 98:
    WakeUpCounter = 6 ms / 0.061 ms = 98.361 =~98
    Therefore, with wake-up counter =  0x62  = 98
    Wakeup Time =  0.061 ms  * 98 = 5.978 ms = ~6 ms. */
    
    wakeUpCounter = (uint16_t)(sleep/RTC_WAKEUP_TIMEBASE);
    HAL_RTCEx_SetWakeUpTimer_IT(&RtcHandle, wakeUpCounter, RTC_WAKEUPCLOCK_RTCCLK_DIV2);
    HAL_NVIC_EnableIRQ(RTC_WKUP_IRQn);
}
 
void rtc_stopWakeupTimer(void)
{
    /* Disable wakeup source*/
    HAL_RTCEx_DeactivateWakeUpTimer(&RtcHandle);
  
    /* Clear all related wakeup flags */
    __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
 
    HAL_NVIC_DisableIRQ(RTC_WKUP_IRQn);
}
 
/**
  * @brief  Wake Up Timer Event Callback in non blocking mode
  * @note   This function is called  when RTC_WKUP interrupt took place, inside
  * RTC_WKUP_IRQHandler().
  * @param  hrtc : RTC handle
  * @retval None
  */
void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc)
{
    rtc_stopWakeupTimer();
}
#endif
 
#if LOW_POWER_MODE
/**
  * @brief  This function handles  WAKE UP TIMER  interrupt request.
  * @param  None
  * @retval None
  */
void RTC_WKUP_IRQHandler(void)
{
    HAL_RTCEx_WakeUpTimerIRQHandler(&RtcHandle);
}
#endif

MM..1
Chief II

Try change SLEEP mode to STOP mode, as say explain, this resume is for state when ticks not work, but i mean in SLEEP mode it work.

A3
Associate III

You mean changing SLEEP mode to STOP mode will work. Any reasoning because CMSIS RTOS2 link as shared above doesn't mention that it will work only in Stop mode? In STOP mode, all clocks are disabled which is not feasible for my application.