【FreeRTOS学习笔记】增加多优先级功能
1.TCB 新增成员 Priority
2.修改任务创建函数原型,并且在函数中,要设置 TCB 的优先级
3.静态创建任务的函数修改后,还需在调用它的地方完善形参:
4.此时检查编译正常;
5.把任务插入到对应优先级链表的过程,和设置TCB的优先级一样,都加入到任务创建函数中,这样使用任务时只需创建就行了;
我们知道,就绪任务列表在第一次使用时,需要把根节点的属性初始化一遍;
为了能在第一次使用时调用初始化,我们设置一个变量 numberOfCurrentTask 用来记录当前已创建的任务数,初始值为0;
6.想要实现根据优先级进行调度,就得更改任务切换的实现
如图,在任务切换中,我们始终从任务就绪列表中获取优先级最高的一个节点;
这里离实际完成还有一部分,这部分后面实现;(任务延时之后,要把它移出就绪列表,时间到了再添加回去,因为我们的任务切换算法是从就绪任务列表搜索的)
7.写一个简单的main函数,任务1、2都只改变一个变量然后TaskDelay,主要用来观察到底是哪个任务占用了CPU;
如图:
调试观察:
可知一直是任务2在运行,符合现在的代码;
8.为了在任务调用TaskDelay延时时,能让出CPU给别的任务使用,
那么在TaskDelay延时函数中,不仅需要设置任务的延时时间,还需要把任务从就绪任务列表中删除;
并且在时钟中断服务例程中,当任务的延时时间到了之后,得把它插回就绪链表中;
9.删除节点好写,但是在把节点插回链表的过程中,我发现之前减少任务延时时间的操作,都是通过遍历“就绪”任务列表来实现的;
这非常别扭,因为需要减少延时时间的肯定是被延时的任务,而不应该在就绪任务列表中找啊;
很容易想到一个办法,新建一个延时链表,把被延时的任务,从就绪链表中移除后,都插入该链表(尾部,以后再说优化);
首先新建一个延时任务链表:
由于链表在使用前需要初始化,在原来的初始化链表函数中,我们只初始化了就绪列表,现在还要初始化延时链表:
再次修改延时函数TaskDelay,把被延时的任务从就绪链表中移除:
10.修改时钟服务例程,遍历延时链表而不是就绪列表,并在延时结束时,从延时链表删除,插回到就绪链表中
在之前实现的时钟服务例程中,我们在临界区内更新任务的延时,所以我们更改这部分的函数实现即可:
11.尝试调试,观察任务延时、和任务延时结束,TCB所在的链表是否改变:
即在延时函数 TaskDelay 和 时钟中断服务例程 中打断点:
将就绪列表和延时链表加入到变量观察窗口:
12.调试过程:
成功删除把Task1从就绪列表中删除,添加到延时链表
更新CurrentTCB:
任务2也插入延时链表中,CurrentTCB切为空闲任务Idle:
13.观察任务从延时恢复到就绪:
就绪前:
就绪后,任务2成功从延时链表恢复到就绪链表,并且CurrentTCB 为任务2:
14.逻辑观察仪结果:
如图,感觉不太理想。
15.总结
代码的实现方面还有许多缺点,比如链表的插入和删除的时间等操作都会影响系统的实时效果。
任务切换的过程时间越多,浪费的CPU时间就越多;
任务切换的细节很有很多可以看情况调整的。多掌握能裁剪的能力吧。