UCOS学习日(2)-任务堆栈和任务切换的更详细的剖析

241 阅读6分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

任务堆栈

昨天详细说了任务控制块,今天接着说一下任务堆栈 昨天说到STM32的堆栈地址是默认这种类型的,简单的说就是,栈顶高地址,向下增长 ◎ Full descending 满递减堆栈 堆栈首部是高地址,堆栈向低地址增长。栈指针总是指向堆栈最后一个元素(最后一个元素是最后压入的数据)。

任务控制块及其链表

UCOS中一次定义了两个链表。一个空白的任务控制块链表,一个是已经初始化好分配给任务的任务控制块链表(这样系统会有更快的执行效率) UCOS中有一个变量专门记录当前任务控制块的指针---OSTCBCur 如果UCOS删除一个任务,那么被删除的任务的任务控制块,就会归还给空白的任务控制块链表

已经分配给任务的TCB(任务控制块)就连接在一起。

UCOS还用了一个OSTCBPrioTbl[]指针数组,把已经创建好的任务的TCB地址,存起来。数组的下标就是任务的优先级

任务就绪表

UCOS中用一个 u8类型的OSRydTbl[8] 数组来表示任务的就绪(1)和等待(0)状态 8*8=64所以UCOS-II支持64个任务

为了方便查询再用一个u8变量的每一位来表示那个数组元素中有任务已经处于就绪状态 OSRydGrp 在这里插入图片描述 那么如何根据任务的优先级别来找到它在变量和数组元素中的位置, 例如一个任务的优先级为30,任务就绪 0001 1110 它的低六位是011 110 011则表示它在OSRydGrp中对应的位是第3位,110则表示它在元素中所对应的位即 第6位置1 那么就是OSRydTbl[3]的第6位置1 在这里插入图片描述

在UCOS系统中对优先级的登记(置1),注销(清0),以及最高优先级就绪任务的查找

都是通过常量来进行操作的。这样会让系统实时性更好,不过这都是系统写好的,我觉得了解一下就可以了。也贴出来

登记

在这里插入图片描述

注销

在这里插入图片描述

最高优先级的就绪任务的查找

在这里插入图片描述 在这里插入图片描述

关于任务的调度更详细的剖析

任务调度器有两种,一个是任务级的调度器,一个是中断级的调度器。

任务调度器,切换任务有两步

任务调度器也可以用函数OSSchedLock();和函数OSSchedUnlock();来加锁和解锁,还可以嵌套。

1.获取待运行任务的TCP指针

在任务就绪表中查找已经就绪的最高优先级的任务。任务优先级数 | ˇ 通过任务优先级,去访问OSTCBPrioTbl[]数组,来获取任务TCB的指针。 | ˇ 用指针变量OSTCBHighRdy来保存待运行任务的TCB指针 上面还说到UCOS用一个OSTCBCur的指针变量指向当前运行任务的TCB指针

2.进行断点数据的保存和切换

任务在进行调度的时候,会把当前运行任务的CPU寄存器中的数据保存下来(保存现场数据,书中说叫断点数据看读者自己是怎么理解的。) | ˇ 将待运行任务的现场数据恢复到CPU的各寄存器中去 | ˇ 关键是的要让CPU的堆栈指针SP(进程堆栈指针或主堆栈指针,具体的应用还是要看程序在执行什么操作)指向任务TCB块中的堆栈指针(OSTCBStkPtr)来实现任务的切换

也就是 被中断的任务,CPU的SP指针要保存到自己TCB块中的堆栈指针中, 待运行任务的TCB块中的堆栈指针要,恢复到CPU的SP堆栈指针中去在这里插入图片描述 但是处理器没有对程序计数器(PC)压栈出栈命令。用任务调度函数来实现一个软中断,进入中断服务程序时会自动把断点指针(就是上一次任务被中断时PC寄存器中的值)压入任务栈,而利用中断返回指令IRET能把待运行任务 的断点指针,推入CPU的PC寄存器。这样恢复待运行任务的断点。 由此我自己理解 ==1.任务进行切换的时候把正在运行任务的CPU各寄存器值SP,R1...等保存自己的任务堆栈-==

==2.触发软中断,CPU自动把 正在运行任务CPU中PC寄存器值 压入自己的任务堆栈==

==3.在软中断中,把待运行任务的堆栈中保存的断点数据恢复到CPU寄存器中==

==4.利用中断返回指令IRET命令把待运行任务的== ==断点指针(就是上一次任务被中断时PC寄存器中的值),推入CPU的PC寄存器中。==

==5.至此实现了完整的任务切换==

简单来说就是在实现任务切换时被中止的任务要保存CPU寄存器的全部数据。

==待运行的任务要把== ==1.任务堆栈的指针放到CPU的SP(堆栈指针寄存器)中== ==2.任务堆栈中保存的其他的CPU各寄存器(如R0R1R2等寄存器)的值也要放到CPU中去== ==3.CPU的PC的值也在任务堆栈中,在任务切换时PC值要推入CPU中比较麻烦,要使用OSCtxSw()函数触发一个软中断(UCOS已经写好了)== 我的理解大概就是这样子,至于这些又是SP指针(堆栈指针寄存器)又是CPU的PC(程序计数器)真的很烦,可能本来很简单的事情被我越描述越复杂,不好理解。举一个简单的例子。

一个书房只能一个学生在里面写作业。 A现在书房里面写作业,写到一半,大姨妈来了,放弃了对书房的占有权,把自己的课桌搬到自己的房间。现在书房空了,拳头比较大的B抢到了占有房间的权利,把自己的课桌搬到书房里面去写作业。写了一段时间A的大姨妈走了,要回书房写作业,B把自己的课桌搬到自己的房间去。A把自己的课桌搬进去,就可以继续接着写作业了。

例子可能不太恰当,但大概是这个意思,A和B的课桌,也就是自己的现场数据,自己失去对书房(CPU)的占有权的时候,也就把课桌(现场数据)搬回自己的房间(自己的任务堆栈)

举例子可能是最好的理解,学习本来就是由浅及深的过程,温故而知新,写博客也是为了这个目的。如果还是理解不清楚,我自己理解的不够深刻,语言描述能力也不好直接看下面 图吧 在这里插入图片描述