在前面提过的就绪列表,它里面存的就是各个优先级的链表。
然后我们只要把相应优先级的任务的TCB插入到后面就行。
那么如何实现优先级呢?
pCurrenTCB是一个全局的TCB指针,用于指向优先级最高的就绪任务的TCB,即当前正在运行的TCB。
所以,我们要想让任务支持优先级,即只要解决任务切换的时候,让pCurrenTCB指向最高优先级的就绪任务的TCB就可以。
接下来要解决的就是如何查找优先级最高的就绪任务的TCB。
通用方法
通用方法,简单来说。
首先,从就绪列表中最高优先级的那个链表开始,往下找。
然后判断每个链表中是否有任务存在,没有的话就继续往下找,有的话就跳出循环。
最后将优先级最高的任务更新到pCurrenTCB。
优化方法
Cortex-M内核有一个计算前导零的指令CLZ。
前导零就是计算一个变量从高位开始第一次出现1的位前面的零的个数。
Cortex-M内核单片机的变量为32位,每个位号对应的时任务的优先级,任务就绪时,则将对应的位置1,非就绪时则将对应为置0。
延时列表
当任务需要延时的时候,先将任务挂起,即将任务从就绪列表中删除,然后插入到任务延时列表,同时更新下一个任务的解锁时间xNextTaskUnblockTime。
xNextTaskUnblockTime的值等于系统时基计数器的值xTickCount加上任务需要延时的值xTicksToDelay。当系统时基计数器xTickCount的值与xNextTaskUnblockTime相等时,就表示有任务延时到期了,需要该任务就绪。
这个跟之前linux驱动里面的定时有点像。
这样的好处就是不用在每个任务都进行扫描了,不费时。
需要注意的点是,考虑想加之后溢出的情况,所以会设置两个延时列表,溢出时一个,正常时一个。
时间片
所谓的时间片,就是同一个优先级下可以有多个任务,每个任务轮流地享有相同的CPU时间。
有点像轮询调度RR。
FreeRTOS时间片只能是一个tick,即SysTick的中断周期。
当同一个优先级下有N个任务时,完成一个任务,节点的遍历指针就往后移动一次,使得每个任务可以轮流享有相同的CPU时间。