SPARC結(jié)構(gòu)與實(shí)時內(nèi)核的移植
中斷堆棧
由于編譯器不能在編譯之初就給外部中斷分配一個堆棧幀,所以需要根據(jù)常規(guī)的堆棧幀模擬一個執(zhí)行中斷服務(wù)程序的棧結(jié)構(gòu)。由于中斷存在嵌套,即在中斷過程中發(fā)生更高優(yōu)先級中斷,并且在運(yùn)行中斷服務(wù)子程序的時候有可能改變被中斷線程的寄存器值,所以在中斷服務(wù)子程序中有必要進(jìn)行“保護(hù)現(xiàn)場”和“恢復(fù)現(xiàn)場”。這樣統(tǒng)一考慮,可以將中斷的棧結(jié)構(gòu)設(shè)計(jì)成圖2所示的結(jié)構(gòu)。其中,除了常規(guī)棧結(jié)構(gòu)以外還包括具有控制信息的幾個寄存器%psr,%pc,%npc, %y,%tbr。和被中斷線程的另外兩組寄存器,global寄存器和inputs寄存器。因?yàn)楫?dāng)進(jìn)入中斷服務(wù)子程序時,CWP已經(jīng)減小了1,所以此時的inputs寄存器應(yīng)該是被中斷線程的outputs寄存器。%g0寄存器的值永遠(yuǎn)為0,所以就不再保存。同時這樣的結(jié)構(gòu)能盡量使每組寄存器的第0個寄存器,如%i0,%l0,%g2,%o0的偏移量為8的倍數(shù),可以使用雙字操作來優(yōu)化寄存器保存與恢復(fù)的時間。
3.任務(wù)切換功能實(shí)現(xiàn)
對于一個支持多任務(wù)的實(shí)時內(nèi)核,在實(shí)現(xiàn)移植時,最基本的任務(wù)就是用CPU支持的匯編語言實(shí)現(xiàn)任務(wù)切換的功能,在uC/OS中就是實(shí)現(xiàn)OSCtxSw( )的功能。
任務(wù)堆棧初始化
一般內(nèi)核在創(chuàng)建新任務(wù)時都將初始化一個新的任務(wù)堆棧,其包含有該任務(wù)的入口地址信息,即在任務(wù)切換函數(shù)中需要設(shè)置的PC值。設(shè)置當(dāng)前的堆棧指針(SP),當(dāng)前堆棧幀指針(FP),處理器狀態(tài)寄存器(PSR)中與寄存器窗口相關(guān)的值等。
任務(wù)堆棧的設(shè)計(jì)可以同中斷堆棧的結(jié)構(gòu)相同。由于任務(wù)切換更接近于子線程的調(diào)用,所以在進(jìn)行上下文切換時只需保存PSR的值和當(dāng)前窗口對應(yīng)的32個寄存器的值即可。任務(wù)堆棧相對中斷堆棧結(jié)構(gòu)更簡單。
當(dāng)前任務(wù)的SP,F(xiàn)P保存在%sp(%o6)和%fp(%i6)中,并且SPARC支持對%sp和%fp的讀寫操作,可以將當(dāng)前的%sp值讀出由 WR指令寫入%i6,再將(%sp-0x148)的值寫入%o6,這樣通過分配一個大小為148H的堆棧幀完成新任務(wù)堆棧指針的初始化。
任務(wù)級切換
uC/OS中任務(wù)切換函數(shù)是由軟中斷(TA指令)來實(shí)現(xiàn)的。SPARC不支持對PC的直接操作,但在發(fā)生軟中斷時,CPU會自動將當(dāng)前PC,NPC 的值寫入到%l1,%l2寄存器。而在中斷結(jié)束返回時,CPU再自動將%l1,%l2的值寫入PC,NPC。根據(jù)CPU這一操作,可以將任務(wù)的入口地址以及入口地址的下一個地址分別寫入%l1,%l2。這樣在中斷返回后的下一條指令就是要切換任務(wù)的入口地址,從而實(shí)現(xiàn)了任務(wù)切換。
在切換函數(shù)執(zhí)行完,中斷返回時執(zhí)行語句“JMP %l1;RETT %l2”將新任務(wù)的入口地址寫入到CPU的PC和NPC,完成任務(wù)級切換。
中斷級切換
如果內(nèi)核為可搶占實(shí)時內(nèi)核,任務(wù)調(diào)度(通常在中斷中被調(diào)用)將高優(yōu)先級的任務(wù)置為有效時,需要在當(dāng)前中斷中完成任務(wù)的切換,使高優(yōu)先級任務(wù)盡快得到CPU使用權(quán),并在該高優(yōu)先級任務(wù)執(zhí)行完,且沒有其它高優(yōu)先任務(wù)被響應(yīng)時,繼續(xù)執(zhí)行之前被中斷的任務(wù)。
中斷級切換函數(shù)必須對被中斷的任務(wù)進(jìn)行“現(xiàn)場保護(hù)”,因?yàn)槊總€中斷函數(shù)都有“保護(hù)現(xiàn)場”功能,所以這一操作不難實(shí)現(xiàn)。此外,中斷級切換函數(shù)還需要為新任務(wù)分配一組新的寄存器窗口,即保存當(dāng)前所有Used態(tài)的窗口寄存器的值到堆棧對應(yīng)的幀中??梢苑Q之為Windows_flush,這也是寄存器窗口相關(guān)的操作。最簡單的flush就是在%WIM中將當(dāng)前窗口置為無效窗口,通過SAVE語句將當(dāng)前窗口對應(yīng)的inputs和locals寄存器的值寫入堆棧。通過循環(huán)控制,可以將8個寄存器窗口的值全部保存,并且SAVE指令通過將%o6的值寫入%i6,能自動實(shí)現(xiàn)棧幀的切換。在執(zhí)行 Windows_flush后,當(dāng)前任務(wù)以及其中調(diào)用的各線程的堆棧幀才全部被填充,成為一個連續(xù)堆棧,這樣才做好了到更高優(yōu)先級切換的準(zhǔn)備。中斷級任務(wù)切換的流程圖如圖3。
評論