任务堆栈
昨天详细说了任务控制块,今天接着说一下任务堆栈
昨天说到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)的占有权的时候,也就把课桌(现场数据)搬回自己的房间(自己的任务堆栈)
举例子可能是最好的理解,学习本来就是由浅及深的过程,温故而知新,写博客也是为了这个目的。如果还是理解不清楚,我自己理解的不够深刻,语言描述能力也不好直接看下面 图吧