FreeRTOS task management basics [For Learning and Practice]

The basics of task management using FreeRTOS are explained with concrete descriptions in actual programs while explaining the concepts of configuration, so you can immediately apply them to your practical programs. Although it is intended for learning, it is of course usable in practice.

Task priority and frequency of use

This section explains how to use RTOS to manage tasks for two types of processes A and B in an application program. Let's look at how Process A is executed as TaskA and Process B as TaskB, with and without priority and with and without specifying the frequency of task execution.

 In case two tasks TaskA and TaskB have the same priority, and nothing is specified for the task execution frequency: 

The basic configuration of FreeRTOS specifies the number of ticks per second at 1000, so the time slice (tick) is 1 ms.

In other words, every 1 ms time slice, TaskA and TaskB are alternately switched between running and ready states by the RTOS kernel. During the 1ms time slice, the contents of TaskA and TaskB are repeated, respectively. For example, as shown in the figure, if the time required to execute Process A once is 0.2ms, it will switch to Process B after 5 iterations.

 In case TaskA's priority is higher than TaskB's and TaskA is suspended for 5 ms 

The priority is specified by the numerical value of the fifth argument of the xTaskCreate function from 1 to 5. (If configMAX_PRIORITIES in the configuration header file FreeRTOSConfig.h is set to 5)
In FreeRTOS, the higher the number, the higher the priority. Here, priority 2 is specified for TaskA and priority 1 for TaskB, so TaskA has a higher priority.

vTaskDelay() is used to suspend the execution of TaskA for a certain period of time. The argument of vTaskDelay() is the time to wait. "5" is specified as the argument since Tick is 1 ms, and once TaskA is executed, it will be blocked for 5 ms and suspended. After this, TaskA is switched to TaskB by a context switch and becomes running.

When the waiting time of 5 ms elapses, TaskA is executed again because it has the highest priority. In other words, Process A is executed only once in a cycle of approximately 5 ms.

 In case TaskA has a higher priority than TaskB and TaskA is suspended for 10 ms and TaskB is suspended for 2 ms 

The following example works the same as type3, but passes parameters to the task.
The following example shows how to pass a parameter (value) to a task by specifying a pointer containing the value to be passed as the fourth argument to the xTaskCreate function.

 In case you want to set the exact task execution cycle: 

In the previous examples, the vTaskDelay function was used to add wait time to the task. Since the time required for processing within a task varies, the execution cycle may vary slightly.

Use vTaskDelayUntil() if you want to set the execution cycle precisely. In the configuration shown in the sample figure, the previous task startup time is obtained with xTaskGetTickCount() and passed to vTaskDelayUntil().

In my experience, when this vTaskDelayUntil function was used to accurately set the execution cycle of a task involving motor operation, the motor operation sometimes became unstable during the transitional period between tasks.

Upon closer examination, it appears that the xLastWakeTime value obtained with the xTaskGetTickCount function was undefined immediately after the switchover, so the operation was unstable only immediately after the switchover. This was because operations were being performed on the motor motion control, and the operation value became unstable during the transition between task changes.

There may be other ways to solve the problem, but in this severe situation, the problem was solved by using vTaskDelay() instead of vTaskDelayUntil() in this severe situation.

Until now, the unit of argument for specifying the time to wait was ticks. To set the unit to ms, the FreeRTOS constant portTICK_RATE_MS can be used as shown in the figure to set the unit of the specified value to ms.

If Tick is exactly 1 ms, the unit of the specified value is ms without using the constant portTICK_RATE_MS, but it is useful to use it otherwise.

Task switching

FreeRTOS allows you to arbitrarily enable or disable a specific task among multiple tasks. Tasks registered with the xTaskCreate function are executed sequentially under the control of the RTOS kernel when the program starts.

In actual applications, tasks are registered as multiple functions, but not all registered tasks are always necessary, and there are many applications in which tasks are used by enabling them or replacing them with other tasks as needed.

vTaskResume() and vTaskSupend() are used to switch between such tasks.

Execution example of Task switching xTaskResume():

The function argument specifies the task handler specified in the sixth argument of xTaskCreat(). If the task is enabled, executing vTaskSuspend() will cause the task to be suspended from any state, and executing vTaskResume() will first cause the task to be ready and then, depending on the priority and other conditions, to be running ( Running).

Here is an example of a task switching program.
TaskC is a management task for task switching, and the switch function switches between TaskA and TaskB when the variable "mode" is 0 or 1.

Task Management

I have been explaining task management using RTOS, but RTOS makes it very easy to achieve processes that would otherwise be quite time-consuming. This article is limited to basic RTOS task management, but even with this, most applications can be realized. As you become more familiar with RTOS, you will be able to develop it further and build a more efficient system.

Follow me!