FreeRTOS: osDelay vs HAL_delay

26,026

Solution 1

HAL_Delay is NOT a FreeRTOS function and _osDelay is a function built around FreeRTOS function. (acc @Clifford: ) They both are entirely different functions by different developers for different purposes.

osDelay is part of the CMSIS Library and uses vTaskDelay() internally to introduce delay with the difference that input argument of osDelay is delay time in milliseconds while the input argument of _vTaskDelay() is number of Ticks to be delayed. (acc. @Bence Kaulics:) Using this function, OS will be notified about the delay and OS will change the status of task to blocked for that particular time period.

HAL_Delay is part of the hardware abstraction layer for our processor. It basically uses polling to introduce delay. (acc. @Bence Kaulics:) Using this function, OS won't be notified about the delay. Also if you do not use OS, then HAL_Delay is the default and only blocking delay to use provided by the HAL library. (acc. @Clifford: ) This is part of HAL Library and can be used without FreeRTOS (or when FreeRTOS is not running)

To introduce Delay using FreeRTOS functions, you can use vTaskDelay() or vTaskDelayUntil() after the scheduler has started.

(acc. @Clifford: )
Always Favour FreeRTOS API function if you want your application to be deterministic.
CubeMX is a collection of parts from multiple sources.

Solution 2

There is a task with the highest priority. If you are going to use the HAL_Delay to block the task then probably there won't be a context switch because the scheduler won't be notified that the task currently just polls a tick counter in a while loop and actually does not do any useful operation. Tasks with lower priority won't run.

The other function uses the vTaskDelay function of the OS, I did not peek into its source code, but probably this will notify the OS the current task wants to be blocked for a certain time, so the task's state will change to blocked and the scheduler can switch to a lower prio task in the meanwhile.

Solution 3

It does not look like HAL_Delay() is intended for use with an RTOS because it is a NULL loop delay. If you call HAL_Delay() from an RTOS task then the task will continue to run until the delay has expired. Higher priority tasks will be able to run, but lower priority tasks will be starved of any processing time during the delay period. That is a waste of processing time, power, and can be detrimental to system responsiveness.

osDelay() on the other hand effects a delay using the RTOS. It tells the RTOS that it has nothing to do until the delay period has expired, so the RTOS does not assign any processing time to the task during that period. That saves processing time, potentially saves power, and allows lower priority tasks to get processing time during the delay period. http://www.freertos.org/FAQWhat.html#WhyUseRTOS

Share:
26,026
ARK4579
Author by

ARK4579

Updated on July 05, 2022

Comments

  • ARK4579
    ARK4579 almost 2 years

    While creating FreeRTOS application project with STM32CubeMx, there are two ways you can use to introduce delay, namely osDelay and HAL_Delay.

    What's the difference among them and which one should be preferred?

    osDelay Code:

    /*********************** Generic Wait Functions *******************************/
    /**
    * @brief   Wait for Timeout (Time Delay)
    * @param   millisec      time delay value
    * @retval  status code that indicates the execution status of the function.
    */
    osStatus osDelay (uint32_t millisec)
    {
    #if INCLUDE_vTaskDelay
      TickType_t ticks = millisec / portTICK_PERIOD_MS;
    
      vTaskDelay(ticks ? ticks : 1);          /* Minimum delay = 1 tick */
    
      return osOK;
    #else
      (void) millisec;
    
      return osErrorResource;
    #endif
    }
    

    HAL_Delay Code:

    /**
    * @brief This function provides accurate delay (in milliseconds) based 
    *        on variable incremented.
    * @note In the default implementation , SysTick timer is the source of time base.
    *       It is used to generate interrupts at regular time intervals where uwTick
    *       is incremented.
    * @note ThiS function is declared as __weak to be overwritten in case of other
    *       implementations in user file.
    * @param Delay: specifies the delay time length, in milliseconds.
    * @retval None
    */
    __weak void HAL_Delay(__IO uint32_t Delay)
    {
      uint32_t tickstart = 0;
      tickstart = HAL_GetTick();
      while((HAL_GetTick() - tickstart) < Delay)
      {
      }
    }
    
  • ARK4579
    ARK4579 about 7 years
    hmmm that makes sense. that's why there are two of them so you can use any one of them based on your task requirements
  • Bence Kaulics
    Bence Kaulics about 7 years
    @ARK4579 Also if you do not use OS, then HAL_Delay is the default and only blocking delay to use provided by the HAL library.
  • Clifford
    Clifford about 7 years
    @ARK4579 : No there are two methods because they are independently developed from different providers for entirely different purposes. The HAL can be used without an RTOS (or before teh RTOS is running), and is a lower level service - always favour the RTOS API if you want your application to schedule deterministically. CubeMX is a collection of parts from multiple sources.