前言

  • uCOS-II 是比较经典的一个RTOS,最近在研究 uCOS-II的移植,接触了较多的ARM 汇编

任务切换

  • 任务切换的实质:
  • 每个任务都有自己【独立】的栈空间
  • 每个任务都有自己【独立】的任务控制块(OS_TCB)对象
  • 任务切换时,当前的任务【被切换任务】,保存CPU的所有寄存器到【自己的】栈空间中,【压栈进去】
  • CPU SP 改为【即将切换任务】的栈顶指针 : 即 新任务的任务控制块对象 OS_TCB 中的OSTCBStkPtr
  • 【弹栈操作】,这里前提是【即将切换任务】运行过,保存了上一次【被切换时】的一套【CPU的寄存器】
  • CPU 更改了所有寄存器,就等于【换了工作环境】,接着运行就运行了【新任务】。

打个不恰当的比方

  • 你写个一篇文章,然后保存,接着去写第二篇
  • 你想接着第一篇文章写,就保存当前的文章(第二篇),打开已经写过的【第一篇】文章,接着写。
  • 你想再写第二篇时,又保存第一篇文章,在打开第二篇文章
  • 这个过程就是【保存当】【恢复】的切换过程

PendSV

  • RTOS 一般在 PendSV 的中断处理中实现了任务切换,这个PendSV 设计的相当的巧妙,可以软件的方式触发中断,并且这个中断可以被【悬起】,非常时候任务的切换
  • 任务的保存 : 获取当前 PSP,压栈 ​​R4~R11 R14​​寄存器,这里因为是在 PendSV中断里,所以​​R1~R3、R12、R13、R15(PC)​​已经由CPU自动压栈了
MRS     R0, PSP  ; PSP is process stack pointer
STMFD R0!, {R4-R11, R14} ; Save remaining regs r4-11, R14 on process stack
  • 任务的【恢复】,通过【弹栈】的方式,把压在【即将切换线程】的SP 拿到,然后弹出到所有寄存器,R1~R15
LDR     R0,  [R2]  ; R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr;
LDMFD R0!, {R4-R11, R14} ; Restore r4-11, R14 from new process stack
  • 这里的 寄存器 R2 保存的是 【即将切换任务】任务控制块对象OSTCBStkPtr,这个指针,就是这个【即将切换任务】上次保存的任务栈【SP】

小结

  • 了解任务切换:CPU寄存器保存与恢复的实质
  • 先了解了切换的流程,再弄懂各个注意的【细节】