3.3. Scheduling Tasks: A Quick Overview
Task Priorities and the Ready List
Each task has a user-assigned priority between 0 (the lowest priority) and the compile-time value of configMAX_PRIORITIES-1
(the highest priority). For instance, if configMAX_PRIORITIES
is set to 5, then FreeRTOS will use 5 priority levels: 0 (lowest priority), 1, 2, 3, and 4 (highest priority).
FreeRTOS uses a "ready list" to keep track of all tasks that are currently ready to run. It implements the ready list as an array of task lists like this:
static xList pxReadyTasksLists[ configMAX_PRIORITIES ]; /* Prioritised ready tasks. */
pxReadyTasksLists[0]
is a list of all ready priority 0 tasks, pxReadyTasksLists[1]
is a list of all ready priority 1 tasks, and so on, all the way up to pxReadyTasksLists[configMAX_PRIORITIES-1]
.
The System Tick
The heartbeat of a FreeRTOS system is called the system tick. FreeRTOS configures the system to generate a periodic tick interrupt. The user can configure the tick interrupt frequency, which is typically in the millisecond range. Every time the tick interrupt fires, the vTaskSwitchContext()
function is called. vTaskSwitchContext()
selects the highest-priority ready task and puts it in the pxCurrentTCB
variable like this:
/* Find the highest-priority queue that contains ready tasks. */ while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) ) { configASSERT( uxTopReadyPriority ); --uxTopReadyPriority; } /* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the tasks of the same priority get an equal share of the processor time. */ listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) );
Before the while loop starts, uxTopReadyPriority
is guaranteed to be greater than or equal to the priority of the highest-priority ready task. The while() loop starts at priority level uxTopReadyPriority
and walks down through the pxReadyTasksLists[]
array to find the highest-priority level with ready tasks. listGET_OWNER_OF_NEXT_ENTRY()
then grabs the next ready task from that priority level's ready list.
Now pxCurrentTCB
points to the highest-priority task, and when vTaskSwitchContext()
returns the hardware-dependent code starts running that task.
Those nine lines of code are the absolute heart of FreeRTOS. The other 8900+ lines of FreeRTOS are there to make sure those nine lines are all that's needed to keep the highest-priority task running.
Figure 3.2 is a high-level picture of what a ready list looks like. This example has three priority levels, with one priority 0 task, no priority 1 tasks, and three priority 2 tasks. This picture is accurate but not complete; it's missing a few details which we'll fill in later.
Illegal HTML tag removed : _ FreeRTOS_files/freertos-figures-basic-ready-list.png)
Now that we have the high-level overview out of the way, let's dive in to the details. We'll look at the three main FreeRTOS data structures: tasks, lists, and queues.