μC/OS-II的內(nèi)核結(jié)構(gòu)
圖3.1任務(wù)的狀態(tài)
本文引用地址:http://www.ex-cimer.com/article/201610/305744.htm正在運行的任務(wù)可以通過調(diào)用兩個函數(shù)之一將自身延遲一段時間,這兩個函數(shù)是OSTimeDly()或OSTimeDlyHMSM()。這個任務(wù)于是進入等待狀態(tài),等待這段時間過去,下一個優(yōu)先級最高的、并進入了就緒態(tài)的任務(wù)立刻被賦予了CPU的控制權(quán)。等待的時間過去以后,系統(tǒng)服務(wù)函數(shù)OSTimeTick()使延遲了的任務(wù)進入就緒態(tài)(見3.10節(jié),時鐘節(jié)拍)。
正在運行的任務(wù)期待某一事件的發(fā)生時也要等待,手段是調(diào)用以下3個函數(shù)之一:
OSSemPend(),OSMboxPend(),或OSQPend()。調(diào)用后任務(wù)進入了等待狀態(tài)(WAITING)。當任務(wù)因等待事件被掛起(Pend),下一個優(yōu)先級最高的任務(wù)立即得到了CPU的控制權(quán)。當事件發(fā)生了,被掛起的任務(wù)進入就緒態(tài)。事件發(fā)生的報告可能來自另一個任務(wù),也可能來自中斷服務(wù)子程序。
正在運行的任務(wù)是可以被中斷的,除非該任務(wù)將中斷關(guān)了,或者μC/OS-Ⅱ?qū)⒅袛嚓P(guān)了。被中斷了的任務(wù)就進入了中斷服務(wù)態(tài)(ISR)。響應(yīng)中斷時,正在執(zhí)行的任務(wù)被掛起,中斷服務(wù)子程序控制了CPU的使用權(quán)。中斷服務(wù)子程序可能會報告一個或多個事件的發(fā)生,而使一個或多個任務(wù)進入就緒態(tài)。在這種情況下,從中斷服務(wù)子程序返回之前,μC/OS-Ⅱ要判定,被中斷的任務(wù)是否還是就緒態(tài)任務(wù)中優(yōu)先級最高的。如果中斷服務(wù)子程序使一個優(yōu)先級更高的任務(wù)進入了就緒態(tài),則新進入就緒態(tài)的這個優(yōu)先級更高的任務(wù)將得以運行,否則原來被中斷了的任務(wù)才能繼續(xù)運行。當所有的任務(wù)都在等待事件發(fā)生或等待延遲時間結(jié)束,μC/OS-Ⅱ執(zhí)行空閑任務(wù)(idletask),執(zhí)行OSTaskIdle()函數(shù)。
3.3 任務(wù)控制塊(TaskControlBlocks,OS _TCBs)
一旦任務(wù)建立了,任務(wù)控制塊OS _TCBs將被賦值(程序清單3.3)。任務(wù)控制塊是一個數(shù)據(jù)結(jié)構(gòu),當任務(wù)的CPU使用權(quán)被剝奪時,μC/OS-Ⅱ用它來保存該任務(wù)的狀態(tài)。當任務(wù)重新得到CPU使用權(quán)時,任務(wù)控制塊能確保任務(wù)從當時被中斷的那一點絲毫不差地繼續(xù)執(zhí)行。OS _TCBs全部駐留在RAM中。讀者將會注意到筆者在組織這個數(shù)據(jù)結(jié)構(gòu)時,考慮到了各成員的邏輯分組。任務(wù)建立的時候,OS _TCBs就被初始化了(見第四章任務(wù)管理)。
程序清單 L3.3μC/OS-II任務(wù)控制塊.
typedefstructos_tcb{
OS_STK*OSTCBStkPtr;
#ifOS_TASK_CREATE_EXT_EN
void*OSTCBExtPtr;
OS_STK*OSTCBStkBottom;
INT32UOSTCBStkSize;
INT16UOSTCBOpt;
INT16UOSTCBId;
#endif
structos_tcb*OSTCBNext;
structos_tcb*OSTCBPrev;
#if(OS_Q_EN(OS_MAX_QS>=2))||OS_MBOX_EN||OS_SEM_EN
OS_EVENT*OSTCBEventPtr;
#endif
#if(OS_Q_EN(OS_MAX_QS>=2))||OS_MBOX_EN
void*OSTCBMsg;
#endif
INT16UOSTCBDly;
INT8UOSTCBStat;
INT8UOSTCBPrio;
INT8UOSTCBX;
INT8UOSTCBY;
INT8UOSTCBBitX;
INT8UOSTCBBitY;
#ifOS_TASK_DEL_EN
BOOLEANOSTCBDelReq;
#endif
}OS_TCB;
.OSTCBStkPtr 是指向當前任務(wù)棧頂?shù)闹羔槨?mu;C/OS-Ⅱ允許每個任務(wù)有自己的棧,尤為重
要的是,每個任務(wù)的棧的容量可以是任意的。有些商業(yè)內(nèi)核要求所有任務(wù)棧的容量都一
樣,除非用戶寫一個復雜的接口函數(shù)來改變之。這種限制浪費了RAM,當各任務(wù)需要的棧
空間不同時,也得按任務(wù)中預期棧容量需求最多的來分配??臻g。OSTCBStkPtr是OS_TCB
數(shù)據(jù)結(jié)構(gòu)中唯一的一個能用匯編語言來處置的變量(在任務(wù)切換段的代碼Context-
switchingcode之中,)把OSTCBStkPtr放在數(shù)據(jù)結(jié)構(gòu)的最前面,使得從匯編語言中處理
這個變量時較為容易。
.OSTCBExtPtr 指向用戶定義的任務(wù)控制塊擴展。用戶可以擴展任務(wù)控制塊而不必修改μ
C/OS-Ⅱ的源代碼。.OSTCBExtPtr只在函數(shù)OstaskCreateExt()中使用,故使用時要將
OS_TASK_CREAT_EN設(shè)為1,以允許建立任務(wù)函數(shù)的擴展。例如用戶可以建立一個數(shù)據(jù)結(jié)
構(gòu),這個數(shù)據(jù)結(jié)構(gòu)包含每個任務(wù)的名字,或跟蹤某個任務(wù)的執(zhí)行時間,或者跟蹤切換到某
個任務(wù)的次數(shù)(見例3)。注意,筆者將這個擴展指針變量放在緊跟著堆棧指針的位置,
為的是當用戶需要在匯編語言中處理這個變量時,從數(shù)據(jù)結(jié)構(gòu)的頭上算偏移量比較方便。
.OSTCBStkBottom 是指向任務(wù)棧底的指針。如果微處理器的棧指針是遞減的,即棧存儲器
從高地址向低地址方向分配,則OSTCBStkBottom指向任務(wù)使用的??臻g的最低地址。類似
地,如果微處理器的棧是從低地址向高地址遞增型的,則OSTCBStkBottom指向任務(wù)可以使
用的棧空間的最高地址。函數(shù)OSTaskStkChk()要用到變量OSTCBStkBottom,在運行中檢驗
??臻g的使用情況。用戶可以用它來確定任務(wù)實際需要的??臻g。這個功能只有當用戶在
任務(wù)建立時允許使用OSTaskCreateExt()函數(shù)時才能實現(xiàn)。這就要求用戶將
OS_TASK_CREATE_EXT_EN設(shè)為1,以便允許該功能。
.OSTCBStkSize 存有棧中可容納的指針元數(shù)目而不是用字節(jié)(Byte)表示的棧容量總數(shù)。
也就是說,如果棧中可以保存1,000個入口地址,每個地址寬度是32位的,則實際棧容量
是4,000字節(jié)。同樣是1,000個入口地址,如果每個地址寬度是16位的,則總棧容量只有
2,000字節(jié)。在函數(shù)OSStakChk()中要調(diào)用OSTCBStkSize。同理,若使用該函數(shù)的話,要將
OS_TASK_CREAT_EXT_EN設(shè)為1。
.OSTCBOpt 把“選擇項”傳給OSTaskCreateExt(),只有在用戶將OS_TASK_CREATE_EXT_EN
設(shè)為1時,這個變量才有效。μC/OS-Ⅱ目前只支持3個選擇項(見uCOS_II.H):
OS_TASK_OTP_STK_CHK,OS_TASK_OPT_STK_CLR和OS_TASK_OPT_SAVE_FP。
OS_TASK_OTP_STK_CHK用于告知TaskCreateExt(),在任務(wù)建立的時候任務(wù)棧檢驗功能得
到了允許。OS_TASK_OPT_STK_CLR表示任務(wù)建立的時候任務(wù)棧要清零。只有在用戶需要有
棧檢驗功能時,才需要將棧清零。如果不定義OS_TASK_OPT_STK_CLR,而后又建立、刪除
評論