![](https://iknow-base.cdn.bcebos.com/lxb/notice.png)
uC/os-ii在进行任务切换时,为什么SP(堆栈指针)不和其他寄存器一样压栈?而是存放在TCB(任务控制块)中?
uC/OS II的源码中,OS_TCB结构体的定义中并没有单独保存SP的成员,而是由结构体中的OSTCBStkPtr指针指向的任务堆栈保存着任务切换需要保存的CPU寄存器内容。uC/OS会给每个创建的任务分配一个TCB,TCB中包含了该任务的全部信息。
扩展资料:
uC/os-ii工作原理:
1,要实现多任务机制,那么目标CPU必须具备一种在运行期更改PC的途径,否则无法做到切换。不幸的是,直接设置PC指针,还没有哪个CPU支持这样的指令。但是一般CPU都允许通过类似JMP,CALL这样的指令来间接的修改PC。
2,事实上,在使用CALL指令或者软中断指令来修改PC,主要是软中断。但在一些CPU上,并不存在软中断这样的概念,所以,我们在那些CPU上,使用几条PUSH指令加上一条CALL指令来模拟一次软中断的发生。
3,在uC/OS-II里,每个任务都有一个任务控制块(Task Control Block),这是一个比较复杂的数据结构。在任务控制块的偏移为0的地方,存储着一个指针,它记录了所属任务的专用堆栈地址。
4,事实上,在uC/OS-II内,每个任务都有自己的专用堆栈,彼此之间不能侵犯。这点要求程序员在它们的程序中保证。一般的做法是把它们申明成静态数组。而且要申明成OS_STK类型。当任务有了自己的堆栈,那么就可以将每一个任务堆栈在那里记录到前面谈到的任务控制快偏移为0的地方。
5,以后每当发生任务切换,系统必然会先进入一个中断,这一般是通过软中断或者时钟中断实现。然后系统会先把当前任务的堆栈地址保存起来,仅接着恢复要切换的任务的堆栈地址。由于哪个任务的堆栈里一定也存的是地址,这样,就达到了修改PC为下一个任务的地址的目的。
你看一下邵贝贝的那本书,page 94, 有这么一段话:然后堆栈指针寄存器被保存在当前任务的OS_TCB中。这怎么理解?
原话应该是:"将当前任务的堆栈指针保存到当前任务的OS_TCB中"。意思是说,将OSTCBStkPtr赋值为指向存放任务信息的的堆栈(注意是堆栈,而不是栈,堆栈的其本质只是保存变量内容的一块连续空间,并不用来作为栈使用,常用做法是声明一个数组来分配这块空间)指针,所以堆栈指针并不是SP;
OSCtxSw是通过汇编实现的,函数功能是进行任务切换,其详细实现描述如下:
1. 将当前任务CPU寄存器信息保存进入栈;
2. 将栈中的信息复制到TCB中OSTCBStkPtr指向的堆栈;
3. OSTCBHighRdy中OSTCBStkPtr指向的堆栈内容复制到栈。
4. OSTCBCur = OSTCBHighRdy
5. OSPrioCur = OSPrioHighRdy
6. 将栈中的信息出栈至CPU;
7. 执行返回
这个系统首先要掌握的重点是在理解任务的创建及切换,所以要好好看这一部分,建议直接看源码,源码也没多少,邵贝贝的书几百页呢,好像也没完整的代码,很多关键部分用文字描述,虽然容易理解,但是语言的总是容易误解,而且会错过很多关键的细节,我也看过这本书某些章节,看完以后还是不能了解很多细节,还是懵懵懂懂,所以直接看源码了,在源码中发现不少巧妙的细节,而这些巧妙的地方文字是不好描述甚至不能准确描述的,所以本人认为看代码是不错的方法。