比如現在有兩個任務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的任務切換。