【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时间就越多;

任务切换的细节很有很多可以看情况调整的。多掌握能裁剪的能力吧。

相关