μC/OS-II的內(nèi)核結(jié)構(gòu)
盡的解釋。
OSSched()的所有代碼都屬臨界段代碼。在尋找進(jìn)入就緒態(tài)的優(yōu)先級(jí)最高的任務(wù)過(guò)程
中,為防止中斷服務(wù)子程序把一個(gè)或幾個(gè)任務(wù)的就緒位置位,中斷是被關(guān)掉的。為縮短切
換時(shí)間,OSSched()全部代碼都可以用匯編語(yǔ)言寫(xiě)。為增加可讀性,可移植性和將匯編語(yǔ)言
代碼最少化,OSSched()是用C寫(xiě)的。
3.6 給調(diào)度器上鎖和開(kāi)鎖(LockingandUnLockingtheScheduler)
給調(diào)度器上鎖函數(shù)OSSchedlock()(程序清單L3.9)用于禁止任務(wù)調(diào)度,直到任務(wù)完
成后調(diào)用給調(diào)度器開(kāi)鎖函數(shù)OSSchedUnlock()為止,(程序清單L3.10)。調(diào)用
OSSchedlock()的任務(wù)保持對(duì)CPU的控制權(quán),盡管有個(gè)優(yōu)先級(jí)更高的任務(wù)進(jìn)入了就緒態(tài)。然
而,此時(shí)中斷是可以被識(shí)別的,中斷服務(wù)也能得到(假設(shè)中斷是開(kāi)著的)。OSSchedlock()
和OSSchedUnlock()必須成對(duì)使用。變量OSLockNesting跟蹤OSSchedLock()函數(shù)被調(diào)用的
次數(shù),以允許嵌套的函數(shù)包含臨界段代碼,這段代碼其它任務(wù)不得干預(yù)。μC/OS-Ⅱ允許嵌
套深度達(dá)255層。當(dāng)OSLockNesting等于零時(shí),調(diào)度重新得到允許。函數(shù)OSSchedLock()和
OSSchedUnlock()的使用要非常謹(jǐn)慎,因?yàn)樗鼈冇绊?mu;C/OS-Ⅱ?qū)θ蝿?wù)的正常管理。
當(dāng)OSLockNesting減到零的時(shí)候,OSSchedUnlock()調(diào)用OSSched[L3.10(2)]。
OSSchedUnlock()是被某任務(wù)調(diào)用的,在調(diào)度器上鎖的期間,可能有什么事件發(fā)生了并使一
個(gè)更高優(yōu)先級(jí)的任務(wù)進(jìn)入就緒態(tài)。
調(diào)用OSSchedLock()以后,用戶的應(yīng)用程序不得使用任何能將現(xiàn)行任務(wù)掛起的系統(tǒng)調(diào)用。也就是說(shuō),用戶程序不得調(diào)用OSMboxPend()、OSQPend()、OSSemPend()、OSTaskSuspend
(OS_PR1O_SELF)、OSTimeDly()或OSTimeDlyHMSM(),直到OSLockNesting回零為止。因?yàn)檎{(diào)度器上了鎖,用戶就鎖住了系統(tǒng),任何其它任務(wù)都不能運(yùn)行。
當(dāng)?shù)蛢?yōu)先級(jí)的任務(wù)要發(fā)消息給多任務(wù)的郵箱、消息隊(duì)列、信號(hào)量時(shí)(見(jiàn)第6章任務(wù)間通訊和同步),用戶不希望高優(yōu)先級(jí)的任務(wù)在郵箱、隊(duì)列和信號(hào)量沒(méi)有得到消息之前就取得了CPU的控制權(quán),此時(shí),用戶可以使用禁止調(diào)度器函數(shù)。
程序清單 L3.9 給調(diào)度器上鎖
voidOSSchedLock(void)
{
if(OSRunning==TRUE){
OS_ENTER_CRITICAL();
OSLockNesting++;
OS_EXIT_CRITICAL();
}
}
程序清單L3.10給調(diào)度器開(kāi)鎖.
voidOSSchedUnlock(void)
{
if(OSRunning==TRUE){
OS_ENTER_CRITICAL();
if(OSLockNesting>0){
OSLockNesting--;
if((OSLockNesting|OSIntNesting)==0){(1)
OS_EXIT_CRITICAL();
OSSched();(2)
}else{
OS_EXIT_CRITICAL();
}
}else{
OS_EXIT_CRITICAL();
}
}
}
3.7 空閑任務(wù)(IdleTask)
μC/OS-Ⅱ總是建立一個(gè)空閑任務(wù),這個(gè)任務(wù)在沒(méi)有其它任務(wù)進(jìn)入就緒態(tài)時(shí)投入運(yùn)行。這個(gè)空閑任務(wù)[OSTaskIdle()]永遠(yuǎn)設(shè)為最低優(yōu)先級(jí),即OS_LOWEST_PRI0??臻e任務(wù)OSTaskIdle()什么也不做,只是在不停地給一個(gè)32位的名叫OSIdleCtr的計(jì)數(shù)器加1,統(tǒng)計(jì)任務(wù)(見(jiàn)3.08節(jié),統(tǒng)計(jì)任務(wù))使用這個(gè)計(jì)數(shù)器以確定現(xiàn)行應(yīng)用軟件實(shí)際消耗的CPU時(shí)間。程序清單L3.11是空閑任務(wù)的代碼。在計(jì)數(shù)器加1前后,中斷是先關(guān)掉再開(kāi)啟的,因?yàn)?位以及大多數(shù)16位微處理器的32位加1需要多條指令,要防止高優(yōu)先級(jí)的任務(wù)或中斷服務(wù)子程序從中打入??臻e任務(wù)不可能被應(yīng)用軟件刪除。
程序清單L3.11μC/OS-Ⅱ的空閑任務(wù).
voidOSTaskIdle(void*pdata)
{
pdata=pdata;
for(;;){
OS_ENTER_CRITICAL();
OSIdleCtr++;
OS_EXIT_CRITICAL();
}
}
3.8 統(tǒng)計(jì)任務(wù)
μC/OS-Ⅱ有一個(gè)提供運(yùn)行時(shí)間統(tǒng)計(jì)的任務(wù)。這個(gè)任務(wù)叫做OSTaskStat(),如果用戶將系統(tǒng)定義常數(shù)OS_TASK_STAT_EN(見(jiàn)文件OS_CFG.H)設(shè)為1,這個(gè)任務(wù)就會(huì)建立。一旦得到了允許,OSTaskStat()每秒鐘運(yùn)行一次(見(jiàn)文件OS_CORE.C),計(jì)算當(dāng)前的CPU利用率。換句話說(shuō),OSTaskStat()告訴用戶應(yīng)用程序使用了多少CPU時(shí)間,用百分比表示,這個(gè)值放在一個(gè)有符號(hào)8位整數(shù)OSCPUsage中,精讀度是1個(gè)百分點(diǎn)。
如果用戶應(yīng)用程序打算使用統(tǒng)計(jì)任務(wù),用戶必須在初始化時(shí)建立一個(gè)唯一的任務(wù),在這個(gè)任務(wù)中調(diào)用OSStatInit()(見(jiàn)文件OS_CORE.C)。換句話說(shuō),在調(diào)用系統(tǒng)啟動(dòng)函數(shù)OSStart()之前,用戶初始代碼必須先建立一個(gè)任務(wù),在這個(gè)任務(wù)中調(diào)用系統(tǒng)統(tǒng)計(jì)初始化函數(shù)OSStatInit(),然后再建立應(yīng)用程序中的其它任務(wù)。程序清單L3.12是統(tǒng)計(jì)任務(wù)的示意性代碼。
程序清單L3.12初始化統(tǒng)計(jì)任務(wù).
voidmain(void)
{
OSInit();/* 初始化uC/OS-II(1)*/
/* 安裝uC/OS-II的任務(wù)切換向量 */
/* 創(chuàng)建用戶起始任務(wù)(為了方便討論,這里以TaskStart()作為起始任務(wù))(2)*/
OSStart();/* 開(kāi)始多任務(wù)調(diào)度 (3)*/
}
voidTaskStart(void*pdata)
{
/* 安裝并啟動(dòng)uC/OS-II的時(shí)鐘節(jié)拍 (4)*/
OSStatInit();/* 初始化統(tǒng)計(jì)任務(wù) (5)*/
/* 創(chuàng)建用戶應(yīng)用程序任務(wù) */
for(;;){
/* 這里是TaskStart()的代碼!*/
}
}
因?yàn)橛脩舻膽?yīng)用程序必須先建立一個(gè)起始任務(wù)[TaskStart()],當(dāng)主程序main()調(diào)用系統(tǒng)啟動(dòng)函數(shù)OSStcnt()的時(shí)候,μC/OS-Ⅱ只有3個(gè)要管理的任務(wù):TaskStart()、OSTaskIdle()和OSTaskStat()。請(qǐng)注意,任務(wù)TaskStart()的名稱是無(wú)所謂的,叫什么名字都可以。因?yàn)?mu;C/OS-Ⅱ已經(jīng)將空閑任務(wù)的優(yōu)先級(jí)設(shè)為最低,即OS_LOWEST_PR10,統(tǒng)計(jì)任務(wù)的優(yōu)先級(jí)設(shè)為次低,OS_LOWEST_PR10-1。啟動(dòng)任務(wù)TaskStart()總是優(yōu)先級(jí)最高的任務(wù)。
圖F3.4解釋初始化統(tǒng)計(jì)任務(wù)時(shí)的流程。用戶必須首先調(diào)用的是μC/OS-Ⅱ中的系統(tǒng)初始化函數(shù)OSInit(),該函數(shù)初始化μC/OS-Ⅱ[圖F3.4(2)]。有的處理器(例如Motorola的MC68HC11),不需要“設(shè)置”中斷向量,中斷向量已經(jīng)在ROM中有了。用戶必須調(diào)用OSTaskCreat()或者OSTaskCreatExt()以建立TaskStart()[圖F3.4(3)]。進(jìn)入多任務(wù)的條件準(zhǔn)備好了以后,調(diào)用系統(tǒng)啟動(dòng)函數(shù)OSStart()。這個(gè)函數(shù)將使 TaskStart()開(kāi)始執(zhí)行,因?yàn)門(mén)askStart()是優(yōu)先級(jí)最高的任務(wù)[圖F3.4(4)]]。
評(píng)論