1. 支持多优先级任务
注意:在FreeRTOS中,数字优先级越小,逻辑优先级也越小
就绪列表pxReadyTasksLists[ configMAX_PRIORITIES ]是一个数组,数组里面存的是就绪任务的TCB(准确来说是TCB里面的xStateListItem节点)。
- 任务在创建的时候,会根据任务的优先级将任务插入到就绪列表不同的位置。相同优先级的任务插入到就绪列表里面的同一条链表中。
- pxCurrenTCB是一个全局的TCB指针,用于指向优先级最高的就绪任务的TCB,即当前正在运行的TCB。那么我们要想让任务支持优先级,即只要解决在任务切换(taskYIELD)的时候,让pxCurrenTCB指向最高优先级的就绪任务的TCB就可以。
2. FreeRTOS查找最高优先级任务
查找最高优先级的就绪任务有两种方法,具体由configUSE_PORT_OPTIMISED_TASK_SELECTION这个宏控制,定义为0选择通用方法,定义为1选择根据处理器优化的方法,该宏默认在portmacro.h中定义为1,即使用优化过的方法。
2.1 通用方法
taskRECORD_READY_PRIORITY():用于更新uxTopReadyPriority的值
taskSELECT_HIGHEST_PRIORITY_TASK():用于寻找优先级最高的就绪任务,实质就是更新uxTopReadyPriority和pxCurrentTCB的值
从最高优先级对应的就绪列表数组下标开始寻找当前链表下是否有任务存在,如果没有,则uxTopPriority减一操作,继续寻找下一个优先级对应的链表中是否有任务存在,如果有则跳出while循环,表示找到了最高优先级的就绪任务。
2.2 优化方法
Cortex-M内核有一个计算前导零的指令CLZ,所谓前导零就是计算一个变量(Cortex-M内核单片机的变量为32位)从高位开始第一次出现1的位的前面的零的个数。
taskRECORD_READY_PRIORITY()用于根据传进来的形参(形参就是任务的优先级)将变量uxTopReadyPriority的某个位置1
portRESET_READY_PRIORITY()用于将变量uxTopReadyPriority的某个位清零
taskSELECT_HIGHEST_PRIORITY_TASK()用于寻找优先级最高的就绪任务,实质就是更新uxTopReadyPriority和pxCurrentTCB的值。
3. 代码修改
任务控制块:在任务控制块中增加与优先级相关的成员uxPriority。 |
---|
修改xTaskCreateStatic():增加优先级形参,数值越大,优先级越高。 |
修改prvInitialiseNewTask() :增加优先级形参和优先级初始化相关代码 |
实现prvAddNewTaskToReadyList():将新创建的任务添加到就绪列表 |
实现prvInitialiseTaskLists():初始化任务相关的列表,此处只有就绪列表 |
prvAddTaskToReadyList():将任务添加到就绪列表 |
修改开启任务调度函数vTaskStartScheduler() |
修改vTaskDelay():根据优先级将优先级位图表uxTopReadyPriority中对应的位清零 |
修改vTaskSwitchContext():直接调用函数taskSELECT_HIGHEST_PRIORITY_TASK()寻找到优先级最高的就绪任务的TCB,然后更新到pxCurrentTCB。 |
修改xTaskIncrementTick():在原来的基础上增加:当任务延时时间到,将任务就绪的代码,根据优先级将优先级位图表uxTopReadyPriority中对应的位置位。 |
在main函数中实现创建任务并启动调度器 |