13.3.5 任务就绪
1.就绪列表的定义
任务创建完成以后就会被添加到就绪列表中,FreeRTOS使用不同的列表表示任务的不同状态,在文件“tasks.c”中就定义了6个全局列表来表示不同的任务状态,这些列表如下。

列表功能如下。
①pxReadyTasksLists[configMAX_PRIORITIES]:就绪列表,这是一个基于优先级的列表数组,大小由最大任务优先级的宏configMAX_PRIORITIES决定,在“FreeRTOSConfig.h”文件中定义,可以修改配置。数组的下标对应了任务的优先级,同一优先级的任务统一插入就绪列表的同一条列表中。
②和③是延时任务列表。
④和⑤是基于优先级的延时任务列表和溢出延时列表。
⑥是挂起列表。
2.就绪列表初始化函数prvInitialiseTaskLists()
就绪列表初始化是通过函数prvInitialiseTaskLists()实现的,该函数原型如下。

主要语句功能如下。
①初始化列表,pxReadyTasksLists[uxPriority]表示该函数基于优先级建立一个就绪列表,若configMAX_PRIORITIES=6,则建立的就绪列表如图13.11所示,每个列表是独立的。
②和③初始化DelayedTaskList1、DelayedTaskList2。
④和⑤初始化TasksWaitingTermination、xSuspendedTaskList。
⑥和⑦分别将延时列表传给pxDelayedTaskList和pxOverflowDelayedTaskList列表。
(https://www.daowen.com)
图13.11 就绪列表
3.任务插入就绪列表函数prvAddNewTaskToReadyList()
任务插入就绪列表即将任务的列表项插入就绪列表。任务的列表项是在xTaskCreate()函数里的prvInitialiseNewTask()函数里完成初始化的,是通过初始化任务控制块完成的。任务控制块里面有一个xStateListItem列表项,将任务插入就绪列表里面,就是通过任务控制块的xStateListItem这个节点将该任务的列表项插入就绪列表中来实现的。在创建静态任务时,也可以通过vListInsertEnd()函数将任务插入就绪列表中。
任务插入就绪列表函数prvAddNewTaskToReadyList()原型如下。


主要语句功能如下。
①变量uxCurrentNumberOfTasks为全局变量,用来统计任务数量。
②如果uxCurrentNumberOfTasks为1,说明为第一个任务,prvInitialiseTaskLists()函数进行列表初始化。
③新创建的任务优先级比正在运行的任务优先级高,调整任务控制块pxCurrentTCB为新建任务的任务控制块。
④调用函数prvAddTaskToReadyList()将任务添加到就绪列表中,通过多个宏来实现,语句如下。

语句a宏taskRECORD_READY_PRIORITY((pxTCB)->uxPriority)用来记录处于就绪态的任务,具体通过操作全局变量uxTopReadyPriority来实现。这个变量用来查找处于就绪态的优先级最高任务,查找算法语句如下。

语句b用函数vListInsertEnd()将任务添加到就绪列表末尾。
⑤如果调度器已开启,并且新任务的任务优先级最高,那么就进行一次任务切换,通过函数taskYIELD_IF_USING_PREEMPTION()实现,该函数实际就是在调用portYIELD()函数触发一次PendSV中断,以进行任务切换。