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