新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > μC/OS-II的內核結構

μC/OS-II的內核結構

作者: 時間:2016-10-08 來源:網(wǎng)絡 收藏

讀者可以看出,任務優(yōu)先級的低三位用于確定任務在總就緒表OSRdyTbl[]中的所在位。接下去的三位用于確定是在OSRdyTbl[]數(shù)組的第幾個元素。OSMapTbl[]是在ROM中的(見文件OS_CORE.C)屏蔽字,用于限制OSRdyTbl[]數(shù)組的元素下標在0到7之間,見表3.1

本文引用地址:http://2s4d.com/article/201610/305744.htm

圖3.3μC/OS-Ⅱ就緒表

如果一個任務被刪除了,則用程序清單3.6中的代碼做求反處理。

程序清單L3.6從就緒表中刪除一個任務

if((OSRdyTbl[prio>>3]=~OSMapTbl[prio0x07])==0)

OSRdyGrp=~OSMapTbl[prio>>3];

以上代碼將就緒任務表數(shù)組OSRdyTbl[]中相應元素的相應位清零,而對于OSRdyGrp,

只有當被刪除任務所在任務組中全組任務一個都沒有進入就緒態(tài)時,才將相應位清零。也

就是說OSRdyTbl[prio>>3]所有的位都是零時,OSRdyGrp的相應位才清零。為了找到那個

進入就緒態(tài)的優(yōu)先級最高的任務,并不需要從OSRdyTbl[0]開始掃描整個就緒任務表,只

需要查另外一張表,即優(yōu)先級判定表OSUnMapTbl([256])(見文件 OS_CORE.C)。OSRdyTbl[]

中每個字節(jié)的8位代表這一組的8個任務哪些進入就緒態(tài)了,低位的優(yōu)先級高于高位。利用

這個字節(jié)為下標來查OSUnMapTbl這張表,返回的字節(jié)就是該組任務中就緒態(tài)任務中優(yōu)先級

最高的那個任務所在的位置。這個返回值在0到7之間。確定進入就緒態(tài)的優(yōu)先級最高的任

務是用以下代碼完成的,如程序清單L3.7所示。

程序清單 L3.7 找出進入就緒態(tài)的優(yōu)先級最高的任務

y=OSUnMapTbl[OSRdyGrp];

x=OSUnMapTbl[OSRdyTbl[y]];

prio=(y3)+x;

例如,如果OSRdyGrp的值為二進制01101000,查OSUnMapTbl[OSRdyGrp]得到的值是

3,它相應于OSRdyGrp中的第3位bit3,這里假設最右邊的一位是第0位bit0。類似地,

如果OSRdyTbl[3]的值是二進制11100100,則OSUnMapTbl[OSRdyTbc[3]]的值是2,即第2

位。于是任務的優(yōu)先級Prio就等于26(3*8+2)。利用這個優(yōu)先級的值。查任務控制塊優(yōu)

先級表OSTCBPrioTbl[],得到指向相應任務的任務控制塊OS_TCB的工作就完成了。

3.5 任務調度(TaskScheduling)

μC/OS-Ⅱ總是運行進入就緒態(tài)任務中優(yōu)先級最高的那一個。確定哪個任務優(yōu)先級最

高,下面該哪個任務運行了的工作是由調度器(Scheduler)完成的。任務級的調度是由函

數(shù)OSSched()完成的。中斷級的調度是由另一個函數(shù)OSIntExt()完成的,這個函數(shù)將在以

后描述。OSSched()的代碼如程序清單L3.8所示。

程序清單L3.8任務調度器(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-Ⅱ任務調度所花的時間是常數(shù),與應用程序中建立的任務數(shù)無關。如程序清單

中[L3.8(1)]條件語句的條件不滿足,任務調度函數(shù)OSSched()將退出,不做任務調度。這

個條件是:如果在中斷服務子程序中調用OSSched(),此時中斷嵌套層數(shù)

OSIntNesting>0,或者由于用戶至少調用了一次給任務調度上鎖函數(shù)OSSchedLock(),使

OSLockNesting>0。如果不是在中斷服務子程序調用OSSched(),并且任務調度是允許的,

即沒有上鎖,則任務調度函數(shù)將找出那個進入就緒態(tài)且優(yōu)先級最高的任務[L3.8(2)],進入

就緒態(tài)的任務在就緒任務表中有相應的位置位。一旦找到那個優(yōu)先級最高的任務,

OSSched()檢驗這個優(yōu)先級最高的任務是不是當前正在運行的任務,以此來避免不必要的任

務調度[L3.8(3)]。注意,在μC/OS中曾經(jīng)是先得到OSTCBHighRdy然后和OSTCBCur做比

較。因為這個比較是兩個指針型變量的比較,在8位和一些16位微處理器中這種比較相對

較慢。而在μC/OS-Ⅱ中是兩個整數(shù)的比較。并且,除非用戶實際需要做任務切換,在查任

務控制塊優(yōu)先級表OSTCBPrioTbl[]時,不需要用指針變量來查OSTCBHighRdy。綜合這兩項

改進,即用整數(shù)比較代替指針的比較和當需要任務切換時再查表,使得μC/OS-Ⅱ比μC/OS

在8位和一些16位微處理器上要更快一些。

為實現(xiàn)任務切換,OSTCBHighRdy必須指向優(yōu)先級最高的那個任務控制塊OS_TCB,這是

通過將以OSPrioHighRdy為下標的OSTCBPrioTbl[]數(shù)組中的那個元素賦給OSTCBHighRdy來

實現(xiàn)的[L3.8(4)]。接著,統(tǒng)計計數(shù)器OSCtxSwCtr加1,以跟蹤任務切換次數(shù)[L3.8(5)]。

最后宏調用OS_TASK_SW()來完成實際上的任務切換[L3.8(6)]。

任務切換很簡單,由以下兩步完成,將被掛起任務的微處理器寄存器推入堆棧,然后

將較高優(yōu)先級的任務的寄存器值從棧中恢復到寄存器中。在μC/OS-Ⅱ中,就緒任務的棧結

構總是看起來跟剛剛發(fā)生過中斷一樣,所有微處理器的寄存器都保存在棧中。換句話說,

μC/OS-Ⅱ運行就緒態(tài)的任務所要做的一切,只是恢復所有的CPU寄存器并運行中斷返回指

令。為了做任務切換,運行OS_TASK_SW(),人為模仿了一次中斷。多數(shù)微處理器有軟中斷

指令或者陷阱指令TRAP來實現(xiàn)上述操作。中斷服務子程序或陷阱處理(Traphardler),

也稱作事故處理(exceptionhandler),必須提供中斷向量給匯編語言函數(shù)OSCtxSw()。

OSCtxSw()除了需要OS_TCBHighRdy指向即將被掛起的任務,還需要讓當前任務控制塊

OSTCBCur指向即將被掛起的任務,參見第8章,移植μC/OS-Ⅱ,有關于OSCtxSw()的更詳



關鍵詞:

評論


相關推薦

技術專區(qū)

關閉