六 上下文切換

一   定義

當UCOS-III轉向執行另一項新任務的時候,他保存了當前任務的CPU寄存器到堆棧,並從新任務的堆棧CPU寄存器載入CPU,這個過程叫做上下文切換

上下文切換需要一些開支,CPU的寄存器越多,開支越大。上下文切換的時間基本取決於有多少個CPU寄存器需要被存儲和載入。

上下文切換的代碼是移植UCOS -II 時編寫的,該部分代碼要適用於處理器,這些代碼被放在C和彙編文件中:OS_CPU.H,OS_CPU_C.C,OS_CPU_A.ASM。移植部分在下面會詳細介紹,根據不同的CPU架構,移植的時候需要注意很多不部分細節。

我們先來看一下常見CPU的結構:包含16個整數寄存器(R0~R15)和一箇中斷堆棧寄存器和狀態寄存器。每個寄存器都是32位的,16個整數寄存器都是可以存儲數據或者地址,指令指針寄存器是R15,兩個堆棧指針是R14和R14‘,其實R14是指向任務的堆棧的指針TSP,R14’是指向ISR的堆棧的指針ISP。當CPU接收到一箇中斷的時候自動切換到ISR堆棧(也就是說CPU有獨立用於處理中斷的堆棧)

在uC/OS-III 中,任務切換時的堆棧設置類似於中斷髮生時的那樣,所有的CPU 寄存器都被保存。我們假定任務堆棧中的信息將要被載入到CPU 中,TSP 指向任務堆棧中最後一個被保存的寄存器。程序指針寄存器和狀態寄存器是最先被保存在任務堆棧中。事實上,當中斷髮生時這些是被CPU 自動執行的。其它的寄存器通過軟件被壓入任務堆棧
TSP 不會被保存到堆棧,但會被保存到任務的TCB。ISP 指向當前中斷堆棧的頂部。當中斷服務程序被執行時,處理器把R14"作爲堆棧指針用於指向函數和局部參數。

有兩種上下文切換的方式:一個是任務級的,一個是中斷級的,任務級切換時通過OSCtxSW()實現的,實際上它是被OS_TASK_SW宏調用的中斷級切換是通過調用OSIntCtxSw()實現。它是用彙編語言寫的,保存於OS_CPU_A.ASM。

二  OSCtxSw()

OSCtxSw()實現上下文切換的相關步驟:


1)OSCtxSw()開始執行,保存狀態寄存器和程序指針寄存器到當前的任務堆棧。保存的順序與中斷髮生時CPU 保存寄存器的順序相同。假定SR 先入棧,然後其它寄存器入棧。
2)當任務被停止時,OSCtxSw()保存CPU 的TSP 到該任務的OS_TCB 中,換句話說,OSTCBCurPtr->StkPtr=R14。
3)然後OSCtxSw()將新任務OS_TCB 的頂部地址存入CPU 的TSP 中。換句話說,R14=OSTCBCurPtr->StkPtr。
4)最後,OSCtxSw()將新任務堆棧中R13~~R0 關內容載入CPU寄存器。再然後(此時的會TSP 指向PC,如圖),通過一箇中斷返回指令{比如彙編中的IRET},程序指針寄存器和狀態寄存器被恢復到CPU 的寄存器中。

終上所述,其實就是對前一個任務在遇到比它優先級還高的任務的時候,CPU先停止其任務,並把它的TSP(就是R14裏面的數據)保存到TCB中,然後再把新任務的TCB指針存入TSP。

三  OSIntCtxSw()

在ISR就緒了高優先級的任務B,ISR返回時將不會回到中前的任務A,而是去轉向優先級更高的任務B,但是在此時,由於中斷產生時,已經將任務A的狀態保存到任務A堆棧中,所以ISR無需再保存任務A的狀態,而是直接載入任務B的CPU寄存器到硬件CPU寄存器即可,調用OSIntCtxSw()執行該操作。


1)OSIntCtxSw()將新任務OS_TCB 的頂部堆棧地址值載入CPU 中的TSP。即R14=OSTCBHighRdyPtr->StkPtr。
2)然後OSIntCtxSw()將新堆棧的相關內容載入到CPU 寄存器中。通過一箇中斷返回指令,程序指針寄存器和狀態寄存器被載入

中斷級上下文切換和任務級上下文切換本質上是一致的,只不過中斷級省掉了保存原來堆棧的步驟。

四  總結

上下文切換包括兩個內容,保存就任務的內容,載入新任務的內容
任務級切換時,通過調用OSSched()實現的,中斷級切換時,通過調用OSIntExit來實現的
OSSched()中調用OSCtxSw()實現上下文切換。OSIntExit()中調用OSIntCtxSw()實現上下文切換。然而,OSIntCtxSw()只需用做上下文切換的第二部分,因爲中斷時被中斷任務的CPU 寄存器已經被保存到被中斷任務的堆棧中了。







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章