μC/OS-II的內(nèi)核結(jié)構(gòu)
讀者可以看出,任務(wù)優(yōu)先級的低三位用于確定任務(wù)在總就緒表OSRdyTbl[]中的所在位。接下去的三位用于確定是在OSRdyTbl[]數(shù)組的第幾個元素。OSMapTbl[]是在ROM中的(見文件OS_CORE.C)屏蔽字,用于限制OSRdyTbl[]數(shù)組的元素下標(biāo)在0到7之間,見表3.1
本文引用地址:http://www.2s4d.com/article/201610/305744.htm
圖3.3μC/OS-Ⅱ就緒表
如果一個任務(wù)被刪除了,則用程序清單3.6中的代碼做求反處理。
程序清單L3.6從就緒表中刪除一個任務(wù)
if((OSRdyTbl[prio>>3]=~OSMapTbl[prio0x07])==0)
OSRdyGrp=~OSMapTbl[prio>>3];
以上代碼將就緒任務(wù)表數(shù)組OSRdyTbl[]中相應(yīng)元素的相應(yīng)位清零,而對于OSRdyGrp,
只有當(dāng)被刪除任務(wù)所在任務(wù)組中全組任務(wù)一個都沒有進(jìn)入就緒態(tài)時,才將相應(yīng)位清零。也
就是說OSRdyTbl[prio>>3]所有的位都是零時,OSRdyGrp的相應(yīng)位才清零。為了找到那個
進(jìn)入就緒態(tài)的優(yōu)先級最高的任務(wù),并不需要從OSRdyTbl[0]開始掃描整個就緒任務(wù)表,只
需要查另外一張表,即優(yōu)先級判定表OSUnMapTbl([256])(見文件 OS_CORE.C)。OSRdyTbl[]
中每個字節(jié)的8位代表這一組的8個任務(wù)哪些進(jìn)入就緒態(tài)了,低位的優(yōu)先級高于高位。利用
這個字節(jié)為下標(biāo)來查OSUnMapTbl這張表,返回的字節(jié)就是該組任務(wù)中就緒態(tài)任務(wù)中優(yōu)先級
最高的那個任務(wù)所在的位置。這個返回值在0到7之間。確定進(jìn)入就緒態(tài)的優(yōu)先級最高的任
務(wù)是用以下代碼完成的,如程序清單L3.7所示。
程序清單 L3.7 找出進(jìn)入就緒態(tài)的優(yōu)先級最高的任務(wù)
y=OSUnMapTbl[OSRdyGrp];
x=OSUnMapTbl[OSRdyTbl[y]];
prio=(y3)+x;
例如,如果OSRdyGrp的值為二進(jìn)制01101000,查OSUnMapTbl[OSRdyGrp]得到的值是
3,它相應(yīng)于OSRdyGrp中的第3位bit3,這里假設(shè)最右邊的一位是第0位bit0。類似地,
如果OSRdyTbl[3]的值是二進(jìn)制11100100,則OSUnMapTbl[OSRdyTbc[3]]的值是2,即第2
位。于是任務(wù)的優(yōu)先級Prio就等于26(3*8+2)。利用這個優(yōu)先級的值。查任務(wù)控制塊優(yōu)
先級表OSTCBPrioTbl[],得到指向相應(yīng)任務(wù)的任務(wù)控制塊OS_TCB的工作就完成了。
3.5 任務(wù)調(diào)度(TaskScheduling)
μC/OS-Ⅱ總是運(yùn)行進(jìn)入就緒態(tài)任務(wù)中優(yōu)先級最高的那一個。確定哪個任務(wù)優(yōu)先級最
高,下面該哪個任務(wù)運(yùn)行了的工作是由調(diào)度器(Scheduler)完成的。任務(wù)級的調(diào)度是由函
數(shù)OSSched()完成的。中斷級的調(diào)度是由另一個函數(shù)OSIntExt()完成的,這個函數(shù)將在以
后描述。OSSched()的代碼如程序清單L3.8所示。
程序清單L3.8任務(wù)調(diào)度器(theTaskScheduler)
voidOSSched(void)
{
INT8Uy;
OS_ENTER_CRITICAL();
if((OSLockNesting|OSIntNesting)==0){(1)
y=OSUnMapTbl[OSRdyGrp];(2)
OSPrioHighRdy=(INT8U)((y3)+OSUnMapTbl[OSRdyTbl[y]]);(2)
if(OSPrioHighRdy!=OSPrioCur){(3)
OSTCBHighRdy=OSTCBPrioTbl[OSPrioHighRdy];(4)
OSCtxSwCtr++;(5)
OS_TASK_SW();(6)
}
}
OS_EXIT_CRITICAL();
}
μC/OS-Ⅱ任務(wù)調(diào)度所花的時間是常數(shù),與應(yīng)用程序中建立的任務(wù)數(shù)無關(guān)。如程序清單
中[L3.8(1)]條件語句的條件不滿足,任務(wù)調(diào)度函數(shù)OSSched()將退出,不做任務(wù)調(diào)度。這
個條件是:如果在中斷服務(wù)子程序中調(diào)用OSSched(),此時中斷嵌套層數(shù)
OSIntNesting>0,或者由于用戶至少調(diào)用了一次給任務(wù)調(diào)度上鎖函數(shù)OSSchedLock(),使
OSLockNesting>0。如果不是在中斷服務(wù)子程序調(diào)用OSSched(),并且任務(wù)調(diào)度是允許的,
即沒有上鎖,則任務(wù)調(diào)度函數(shù)將找出那個進(jìn)入就緒態(tài)且優(yōu)先級最高的任務(wù)[L3.8(2)],進(jìn)入
就緒態(tài)的任務(wù)在就緒任務(wù)表中有相應(yīng)的位置位。一旦找到那個優(yōu)先級最高的任務(wù),
OSSched()檢驗這個優(yōu)先級最高的任務(wù)是不是當(dāng)前正在運(yùn)行的任務(wù),以此來避免不必要的任
務(wù)調(diào)度[L3.8(3)]。注意,在μC/OS中曾經(jīng)是先得到OSTCBHighRdy然后和OSTCBCur做比
較。因為這個比較是兩個指針型變量的比較,在8位和一些16位微處理器中這種比較相對
較慢。而在μC/OS-Ⅱ中是兩個整數(shù)的比較。并且,除非用戶實際需要做任務(wù)切換,在查任
務(wù)控制塊優(yōu)先級表OSTCBPrioTbl[]時,不需要用指針變量來查OSTCBHighRdy。綜合這兩項
改進(jìn),即用整數(shù)比較代替指針的比較和當(dāng)需要任務(wù)切換時再查表,使得μC/OS-Ⅱ比μC/OS
在8位和一些16位微處理器上要更快一些。
為實現(xiàn)任務(wù)切換,OSTCBHighRdy必須指向優(yōu)先級最高的那個任務(wù)控制塊OS_TCB,這是
通過將以O(shè)SPrioHighRdy為下標(biāo)的OSTCBPrioTbl[]數(shù)組中的那個元素賦給OSTCBHighRdy來
實現(xiàn)的[L3.8(4)]。接著,統(tǒng)計計數(shù)器OSCtxSwCtr加1,以跟蹤任務(wù)切換次數(shù)[L3.8(5)]。
最后宏調(diào)用OS_TASK_SW()來完成實際上的任務(wù)切換[L3.8(6)]。
任務(wù)切換很簡單,由以下兩步完成,將被掛起任務(wù)的微處理器寄存器推入堆棧,然后
將較高優(yōu)先級的任務(wù)的寄存器值從棧中恢復(fù)到寄存器中。在μC/OS-Ⅱ中,就緒任務(wù)的棧結(jié)
構(gòu)總是看起來跟剛剛發(fā)生過中斷一樣,所有微處理器的寄存器都保存在棧中。換句話說,
μC/OS-Ⅱ運(yùn)行就緒態(tài)的任務(wù)所要做的一切,只是恢復(fù)所有的CPU寄存器并運(yùn)行中斷返回指
令。為了做任務(wù)切換,運(yùn)行OS_TASK_SW(),人為模仿了一次中斷。多數(shù)微處理器有軟中斷
指令或者陷阱指令TRAP來實現(xiàn)上述操作。中斷服務(wù)子程序或陷阱處理(Traphardler),
也稱作事故處理(exceptionhandler),必須提供中斷向量給匯編語言函數(shù)OSCtxSw()。
OSCtxSw()除了需要OS_TCBHighRdy指向即將被掛起的任務(wù),還需要讓當(dāng)前任務(wù)控制塊
OSTCBCur指向即將被掛起的任務(wù),參見第8章,移植μC/OS-Ⅱ,有關(guān)于OSCtxSw()的更詳
評論