Приоритеты задач
Планировщик задач, опираясь на приоритет, определяет, какая задача должна быть запущена раньше других. Данное свойство — не что иное, как число от 0
до configMAX_PRIORITIES
(определена в FreeRTOSConfig.h
), причем приоритет 0
строго зарезервирован под idle
-задачу. Чем больше число, тем выше приоритет. То, как ведут себя задачи с одинаковым приоритетом при разной настройке системы, мы рассматривали выше. Отметим лишь, что за временное разделение отвечает параметр configTICK_RATE_HZ
в файле FreeRTOSConfig.h
.
В FreeRTOS нет механизмов, предотвращающих ситуации, когда одна задача оккупирует все процессорное время; это задача программиста.
Приоритет задается при создании задачи и может быть изменен во время ее выполнения через функции vTaskPriorityGet()
и vTaskPrioritySet()
.
CMSIS-RTOS определяет приоритеты по-другому.
typedef enum {
osPriorityIdle = -3, ///< priority: idle (lowest)
osPriorityLow = -2, ///< priority: low
osPriorityBelowNormal = -1, ///< priority: below normal
osPriorityNormal = 0, ///< priority: normal (default)
osPriorityAboveNormal = +1, ///< priority: above normal
osPriorityHigh = +2, ///< priority: high
osPriorityRealtime = +3, ///< priority: realtime (highest)
osPriorityError = 0x84 ///< system cannot determine priority or thread has illegal priority
} osPriority;
Планировщик задач
Для хранения параметров задачи, таких как ее приоритет, идентификатор, указатель на стек, его вершину или название (нужно исключительно для отладки), FreeRTOS использует структуру tskTCB
(сокр. с англ. Task Control Block). Планировщик создает из таких структур двусвязные списки xList
(из файла list.c
) для контроля за состоянием задач. Каждому состоянию соответствует собственный список, который поддерживается в отсортированном видеlinked_list. Изменение состояния осуществляется простым переносом задачи из одного списка в другой.[linked_list] Структура данных «двухсвязный список» используется не случайно — так как список поддерживается в отсортированном виде, требуется переписать пару указателей при добавлении или удалении задачи из списка.
static xList pxReadyTasksLists[ configMAX_PRIORITIES ];
Здесь pxReadyTasksLists[0]
содержит все задачи с приоритетом 0
, pxReadyTasksLists[1]
— с приоритетом 1
и так далее вплоть до pxReadyTasksLists[configMAX_PRIORITIES-1]
. Как только наступает системный тик (или задача возвращает управление), вызывается функция vTaskSwitchContext()
. Ее миссия — просмотреть все списки задач, перенести заблокированные задачи в состояние готовности, если их пора выполнить, а затем выбрать наиболее приоритетную задачу и сменить контекст. Для того чтобы всё это работало, планировщик необходимо запустить через функцию vTaskStartScheduler()
(osKernelStart()
).