μC/OS-II的任務(wù)管理
在前面的章節(jié)中,筆者曾說過任務(wù)可以是一個無限的循環(huán),也可以是在一次執(zhí)行完畢后被刪除掉。這里要注意的是,任務(wù)代碼并不是被真正的刪除了,而只是μC/OS-Ⅱ不再理會該任務(wù)代碼,所以該任務(wù)代碼不會再運行。任務(wù)看起來與任何C函數(shù)一樣,具有一個返回類型和一個參數(shù),只是它從不返回。任務(wù)的返回類型必須被定義成void型。在本章中所提到的函數(shù)可以在OS_TASK文件中找到。如前所述,任務(wù)必須是以下兩種結(jié)構(gòu)之一:
本文引用地址:http://www.ex-cimer.com/article/201610/305743.htmvoidYourTask(void*pdata)
{
for(;;){
/* 用戶代碼 */
調(diào)用μC/OS-Ⅱ的服務(wù)例程之一:
OSMboxPend();
OSQPend();
OSSemPend();
OSTaskDel(OS_PRIO_SELF);
OSTaskSuspend(OS_PRIO_SELF);
OSTImeDly();
OSTimeDlyHMSM();
/* 用戶代碼 */
}
}
或
voidYourTask(void*pdata)
{
/* 用戶代碼 */
OSTaskDel(OS_PRIO_SELF);
}
本章所講的內(nèi)容包括如何在用戶的應(yīng)用程序中建立任務(wù)、 刪除任務(wù)、 改變?nèi)蝿?wù)的優(yōu)先級、掛起和恢復任務(wù),以及獲得有關(guān)任務(wù)的信息。
μC/OS-Ⅱ可以管理多達64個任務(wù),并從中保留了四個最高優(yōu)先級和四個最低優(yōu)先級的任務(wù)供自己使用,所以用戶可以使用的只有56個任務(wù)。任務(wù)的優(yōu)先級越高,反映優(yōu)先級的值則越低。在最新的μC/OS-Ⅱ版本中,任務(wù)的優(yōu)先級數(shù)也可作為任務(wù)的標識符使用。
4.0 建立任務(wù),OSTaskCreate()
想讓μC/OS-Ⅱ管理用戶的任務(wù),用戶必須要先建立任務(wù)。用戶可以通過傳遞任務(wù)地址和其它參數(shù)到以下兩個函數(shù)之一來建立任務(wù):OSTaskCreate()或OSTaskCreateExt()。
OSTaskCreate()與μC/OS是向下兼容的, OSTaskCreateExt()是 OSTaskCreate()的擴展版本,提供了一些附加的功能。用兩個函數(shù)中的任何一個都可以建立任務(wù)。任務(wù)可以在多任務(wù)調(diào)度開始前建立,也可以在其它任務(wù)的執(zhí)行過程中被建立。在開始多任務(wù)調(diào)度(即調(diào)用OSStart())前,用戶必須建立至少一個任務(wù)。任務(wù)不能由中斷服務(wù)程序(ISR)來建立。
OSTaskCreate()的代碼如程序清單L4.1所述。從中可以知道,OSTaskCreate()需要四個參數(shù): task是任務(wù)代碼的指針, pdata是當任務(wù)開始執(zhí)行時傳遞給任務(wù)的參數(shù)的指針, ptos是分配給任務(wù)的堆棧的棧頂指針(參看4.02,任務(wù)堆棧),prio是分配給任務(wù)的優(yōu)先級。
程序清單 L4.1 OSTaskCreate()
INT8UOSTaskCreate(void(*task)(void*pd),void*pdata,OS_STK*ptos,
INT8Uprio)
{
void*psp;
INT8Uerr;
if(prio>OS_LOWEST_PRIO){(1)
return(OS_PRIO_INVALID);
}
OS_ENTER_CRITICAL();
if(OSTCBPrioTbl[prio]==(OS_TCB*)0){(2)
OSTCBPrioTbl[prio]=(OS_TCB*)1;(3)
OS_EXIT_CRITICAL();(4)
psp=(void*)OSTaskStkInit(task,pdata,ptos,0);(5)
err=OSTCBInit(prio,psp,(void*)0,0,0,(void*)0,0);(6)
if(err==OS_NO_ERR){(7)
OS_ENTER_CRITICAL();
OSTaskCtr++;(8)
OSTaskCreateHook(OSTCBPrioTbl[prio]);(9)
OS_EXIT_CRITICAL();
if(OSRunning){(10)
OSSched();(11)
}
}else{
OS_ENTER_CRITICAL();
OSTCBPrioTbl[prio]=(OS_TCB*)0;(12)
OS_EXIT_CRITICAL();
}
return(err);
}else{
OS_EXIT_CRITICAL();
return(OS_PRIO_EXIST);
}
}
OSTaskCreate()一開始先檢測分配給任務(wù)的優(yōu)先級是否有效[L4.1(1)]。任務(wù)的優(yōu)先級必須在0到OS_LOWEST_PRIO之間。接著,OSTaskCreate()要確保在規(guī)定的優(yōu)先級上還沒有建立任務(wù)[L4.1(2)]。在使用μC/OS-Ⅱ時,每個任務(wù)都有特定的優(yōu)先級。如果某個優(yōu)先級是空閑的,μC/OS-Ⅱ通過放置一個非空指針在OSTCBPrioTbl[]中來保留該優(yōu)先級[L4.1(3)]。
這就使得OSTaskCreate()在設(shè)置任務(wù)數(shù)據(jù)結(jié)構(gòu)的其他部分時能重新允許中斷[L4.1(4)]。然后,OSTaskCreate()調(diào)用OSTaskStkInit()[L4.1(5)],它負責建立任務(wù)的堆棧。該函數(shù)是與處理器的硬件體系相關(guān)的函數(shù),可以在OS_CPU_C.C文件中找到。有關(guān)實現(xiàn)OSTaskStkInit()的細節(jié)可參看第8章——移植μC/OS-Ⅱ。如果已經(jīng)有人在你用的處理器上成功地移植了μC/OS-Ⅱ,而你又得到了他的代碼,就不必考慮該函數(shù)的實現(xiàn)細節(jié)了。
OSTaskStkInit()函數(shù)返回新的堆棧棧頂(psp),并被保存在任務(wù)的0S_TCB中。 注意用戶得將傳遞給OSTaskStkInit()函數(shù)的第四個參數(shù)opt置0,因為OSTaskCreate()與OSTaskCreateExt()不同,它不支持用戶為任務(wù)的創(chuàng)建過程設(shè)置不同的選項,所以沒有任何選項可以通過opt參數(shù)傳遞給OSTaskStkInit()。
μC/OS-Ⅱ支持的處理器的堆棧既可以從上(高地址)往下(低地址)遞減也可以從下往上遞增。用戶在調(diào)用OSTaskCreate()的時候必須知道堆棧是遞增的還是遞減的(參看所用處理器的OS_CPU.H中的OS_STACK_GROWTH),因為用戶必須得把堆棧的棧頂傳遞給OSTaskCreate(), 而棧頂可能是堆棧的最高地址(堆棧從上往下遞減), 也可能是最低地址(堆棧從下往上長)。
一旦OSTaskStkInit()函數(shù)完成了建立堆棧的任務(wù),OSTaskCreate()就調(diào)用OSTCBInit()[L4.1(6)],從空閑的OS_TCB池中獲得并初始化一個OS_TCB。OSTCBInit()的代碼如程序清單L4.2所示,它存在于0S_CORE.C文件中而不是OS_TASK.C文件中。
OSTCBInit()函數(shù)首先從OS_TCB緩沖池中獲得一個OS_TCB[L4.2(1)],如果OS_TCB池中有空閑的OS_TCB[L4.2(2)],它就被初始化[L4.2(3)]。注意一旦OS_TCB被分配,該任務(wù)的創(chuàng)建者就已經(jīng)完全擁有它了,即使這時內(nèi)核又創(chuàng)建了其它的任務(wù),這些新任務(wù)也不可能對已分配的OS_TCB作任何操作,所以O(shè)STCBInit()在這時就可以允許中斷,并繼續(xù)初始化OS_TCB的數(shù)據(jù)單元。
程序清單 L4.2 OSTCBInit()
INT8UOSTCBInit(INT8Uprio,OS_STK*ptos,OS_STK*pbos,INT16Uid,
INT16Ustk_size,void*pext,INT16Uopt)
評論