比如现在有两个任务task1 和task2
现在将运行着的task1 切换到 task2
有图M3有PSP和MSP,任务是在PSP保存堆栈指针的,由一个任务切换到另一个任务,就是说
要把PSP里面的指针由 task1的堆栈指针换成 task2的堆栈指针,这个过程就是上下文切换,对应UCOS里
面的void OS_Sched (void)函数,这个函数里面的功能实际是由OSCtxSw()函数完成的,而这个函
数是由汇编写成的,如下
OSCtxSw
LDR R0, =NVIC_INT_CTRL ; Trigger the PendSV exception (causes context switch)
LDR R1, =NVIC_PENDSVSET
STR R1, [R0]
BX LR
而这个汇编的代码目的是触发一个PendSV异常,从而实现上下文切换(causes context switch)。
然后,
这个PendSV异常做的事情就是下面的这个链接所讲的事情:
”uCOS-II在Cortext-M3(STM32)上的任务切换示意 转载来源:https://blog.csdn.net/_xiao/article/details/78481598”,
简单的来讲,上面这个链接里面的内容可以概括如下:
一个PendSV异常来了,CPU进入到Handler模式,当要进行task1切换到task2的时
候,CPU里面的全部寄存器(包含xPSR,PC,LR,R12,R0~R3 另外加上R4-R11)保存到PSP所指向的task1的堆
栈(自己创建的,大小由自己定)里面去,
然后PendSV异常从OSTCBHighRdy()获取需要切换到的任务块(此时为task2的任务控制块TCB2),然后从TCB2的获取task2的堆栈指针到CPU的PSP寄存器。
然后,将task2堆栈里面的数据恢复到CPU寄存器中。
CPU退出异常模式(Handler模式),切换到线程模式,重新使用PSP堆栈作为工作堆栈(此时PSP已指向Task2的堆栈),即是使用Task2的堆栈作为工作堆栈。
CPU已恢复到Task2挂起前的现场,从Task2被中断的PC处继续运行。
概括结束。
到此,就完成了task1到task2的任务切换。