嵌入式實時操作系統(tǒng)ucosII_第1頁
嵌入式實時操作系統(tǒng)ucosII_第2頁
嵌入式實時操作系統(tǒng)ucosII_第3頁
嵌入式實時操作系統(tǒng)ucosII_第4頁
嵌入式實時操作系統(tǒng)ucosII_第5頁
已閱讀5頁,還剩345頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

嵌入式操作系統(tǒng)基礎(chǔ)——C/OS-Ⅱ

“嵌入式操作系統(tǒng)基礎(chǔ)”課程內(nèi)容132548嵌入式實時操作系統(tǒng)C/OS-Ⅱ操作系統(tǒng)及任務(wù)C/OS-Ⅱ的中斷、時鐘及時間管理C/OS-Ⅱ的任務(wù)管理C/OS-Ⅱ的初始化、啟動C/OS-Ⅱ的移植6C/OS-Ⅱ任務(wù)通信與同步7C/OS-Ⅱ內(nèi)存管理9基于C/OS-Ⅱ應(yīng)用的開發(fā)

第一講嵌入式實時操作系統(tǒng)第一節(jié)嵌入式系統(tǒng)目前國內(nèi)一個普遍被認(rèn)同的定義是:以應(yīng)用為中心、以計算機(jī)技術(shù)為基礎(chǔ),軟件硬件可裁剪,適應(yīng)應(yīng)用系統(tǒng)對功能、可靠性、成本、體積、功耗嚴(yán)格要求的專用計算機(jī)系統(tǒng)。而這專用計算機(jī)系統(tǒng)是嵌入到對象中。只見對象,不見計算機(jī)。如圖1.1、1.2、1.3、1.4所示。這個專用計算機(jī)系統(tǒng)承擔(dān)對象的數(shù)據(jù)處理和對象各部件運(yùn)動的控制。隨著大規(guī)模集成電路的發(fā)展、嵌入式軟件工程的發(fā)展,嵌入的對象越來越廣泛。第二節(jié)

嵌入式實時操作系統(tǒng)正如通用計算機(jī)系統(tǒng),有很多軟、硬件資源需要一個操作系統(tǒng)來管理,并提供用戶一個良好的程序運(yùn)行的環(huán)境。同樣,作為嵌入式系統(tǒng)—專用計算機(jī)也需要一個操作系統(tǒng)。這個操作系統(tǒng)必須是實時的、嵌入式的。許多早期的嵌入式系統(tǒng)開發(fā)者認(rèn)為嵌入式系統(tǒng)不需要操作系統(tǒng),但現(xiàn)在除了最簡單的系統(tǒng)外,越來越多的嵌入式系統(tǒng)都引入了操作系統(tǒng),比如中斷驅(qū)動系統(tǒng)在引入嵌入式操作系統(tǒng)之后,系統(tǒng)的可靠性、安全性、可擴(kuò)展性、功能性、靈活性、可管理性都大大提高。當(dāng)然,我們這里所講的嵌入式操作系統(tǒng)不一定是UcOS、VxWorks、WinCE、Linux等通用產(chǎn)品,也包括開發(fā)者自己編寫的專用嵌入式操作系統(tǒng)。

嵌入式實時操作系統(tǒng)在這些嵌入式操作系統(tǒng)中封裝了越來越多的功能,除了對任務(wù)的切換、調(diào)度、通信、同步、互斥、中斷管理、時鐘管理等,還可進(jìn)一步封裝內(nèi)存管理、網(wǎng)絡(luò)通訊協(xié)議、文件管理等功能,這些功能可以根據(jù)需要進(jìn)行裁減。Linux正是由于其源代碼開放,可以使開發(fā)者根據(jù)自己的需要進(jìn)行裁剪而受到開發(fā)者的青睞。1.2.1計算機(jī)實時操作系統(tǒng)實時操作系統(tǒng)首要特點是實時性。為此:⑴實時操作系統(tǒng)必須是多任務(wù)的。⑵實時操作系統(tǒng)內(nèi)核應(yīng)該是可剝奪型的。

圖1.1

圖1.2

圖1.3

圖1.4

關(guān)于內(nèi)核應(yīng)該是可剝奪型的這種可剝奪性表現(xiàn)為:一個在運(yùn)行的進(jìn)程可被另一個進(jìn)程剝奪其在CPU的運(yùn)行權(quán);另一方面,被剝奪運(yùn)行權(quán)的進(jìn)程,一旦再次獲得運(yùn)行時,能夠正確無誤運(yùn)行,得到正確結(jié)果。為此,編譯器、程序設(shè)計都要保證這點。①可重入函數(shù) ②不可重入的函數(shù)viodstrcpy(char*dest,char*src) intTemp;{ voidswap(int*x,int*y)while(*dest++=*src++){ {; Temp=*x;} *x=*y;*dest=NULL; *y=Temp;} }對于含有不可剝奪的函數(shù)的進(jìn)程是不剝奪的。⑶進(jìn)程調(diào)度的延時可預(yù)測并盡可能?、认到y(tǒng)提供的服務(wù)時間可預(yù)知.

嵌入式實時操作系統(tǒng)

實時嵌入式操作系統(tǒng)的種類繁多,大體上可分為兩種,商用型和免費(fèi)型。商用型的實操作系統(tǒng)功能穩(wěn)定、可靠,有完善的技術(shù)支持和售后服務(wù),但往往價格昂貴,如Vxworks、QNX、WinCE、PalmOS等。免費(fèi)型的實時操作系統(tǒng)在價格方面具有優(yōu)勢,目前主要有Linux、eCos和μC/OS-Ⅱ,穩(wěn)定性與服務(wù)性存在挑戰(zhàn)。μC/OS-Ⅱ得到了美國航空管理局的認(rèn)證,可用在飛行器上。這說明μC/OS-Ⅱ是穩(wěn)定可靠的,可用在與人性命攸關(guān)的安全緊要的系統(tǒng)上。本課程講授的就是μC/OS-Ⅱ。它是一個十分小的內(nèi)核。⑸中斷延時盡可能小。否則影響高優(yōu)先級進(jìn)程的執(zhí)行。1.2.2嵌入式實時操作系統(tǒng)嵌入式系統(tǒng)是嵌入到某一對象中的專用計算機(jī),它所占用的空間和所需的能源十分有限,甚至是苛刻的。這就要求操作系統(tǒng)是可剪裁的。對于不同的應(yīng)用對象,必須剪裁掉與其無關(guān)的部分。這樣嵌入式系統(tǒng)不但是實時的,而且是可剪裁的。這點與通用操作系統(tǒng)是不同的.

學(xué)習(xí)嵌入式操作系統(tǒng)學(xué)習(xí)一種實時操作系統(tǒng)RTOS,如uc/OS,掌握實時系統(tǒng)的概念和設(shè)計方法;嵌入式系統(tǒng)以應(yīng)用為中心,應(yīng)用時選擇“適用”的操作系統(tǒng);知道如何剪裁操行系統(tǒng);嵌入式Linux、eCos;自己“寫”RTOS——一種學(xué)習(xí)態(tài)度;由于嵌入式系統(tǒng)自身的特點,采用的程序設(shè)計語言是匯編語言、C/C++語言、JAVA語言。所用的編譯器應(yīng)與處理器相適應(yīng)。

RTOS在嵌入式系統(tǒng)中的位置嵌入式硬件平臺BSP(板級支持包)KERNELFSTCP/IP設(shè)備驅(qū)動設(shè)備I/O調(diào)試工具其它組件應(yīng)用RTOSC/C++

第二講

C/OS

–II及任務(wù)μC/OS-II的特點μC/OS-II文件結(jié)構(gòu)與內(nèi)核μC/OS-II任務(wù)及其存儲結(jié)構(gòu)μC/OS-II任務(wù)控制塊與任務(wù)堆棧μC/OS-II系統(tǒng)的任務(wù)、空閑任務(wù)與統(tǒng)計任務(wù)

公開源代碼可移植性(Portable)

絕大部分

C/OS-II的源碼是用移植性很強(qiáng)的ANSIC寫的。和微處理器硬件相關(guān)的那部分是用匯編語言寫的。匯編語言寫的部分已經(jīng)壓到最低限度,使得

C/OS-II便于移植到其他微處理器上。

C/OS-II可以在絕大多數(shù)8位、16位、32位以至64位微處理器、微控制器、數(shù)字信號處理器(DSP)上運(yùn)行??晒袒≧OMable)

C/OS-II是為嵌入式應(yīng)用而設(shè)計的,這就意味著,只要讀者有固化手段(C編譯、連接、下載和固化),

C/OS-II可以嵌入到讀者的產(chǎn)品中成為產(chǎn)品的一部分??刹眉簦⊿calable)

可以只使用

C/OS-II中應(yīng)用程序需要的那些系統(tǒng)服務(wù)。也就是說某產(chǎn)品可以只使用很少幾個

C/OS-II調(diào)用,而另一個產(chǎn)品則使用了幾乎所有

C/OS-II的功能,這樣可以減少產(chǎn)品中的

C/OS-II所需的存儲器空間(RAM和ROM)。這種可剪裁性是靠條件編譯實現(xiàn)的。第一節(jié)C/OS的性能特點(一)

占先式(Preemptive)多任務(wù)

C/OS-II可以管理64個任務(wù),然而,目前這一版本保留8個給系統(tǒng)。應(yīng)用程序最多可以有56個任務(wù)可確定性

全部

C/OS-II的函數(shù)調(diào)用與服務(wù)的執(zhí)行時間具有可確定性。任務(wù)棧

每個任務(wù)有自己單獨的棧,

C/OS-II允許每個任務(wù)有不同的??臻g,以便壓低應(yīng)用程序?qū)AM的需求。系統(tǒng)服務(wù)

C/OS-II提供很多系統(tǒng)服務(wù),例如郵箱、消息隊列、信號量、塊大小固定的內(nèi)存的申請與釋放、時間相關(guān)函數(shù)等。中斷管理

中斷可以使正在執(zhí)行的任務(wù)暫時掛起,如果優(yōu)先級更高的任務(wù)被該中斷喚醒,則高優(yōu)先級的任務(wù)在中斷嵌套全部退出后立即執(zhí)行,中斷嵌套層數(shù)可達(dá)255層。穩(wěn)定性與可靠性C/OS的性能特點(二)

第二節(jié)C/OS-II的文件結(jié)構(gòu)與內(nèi)核

任務(wù)管理:任務(wù)的描述、任務(wù)的創(chuàng)建、任務(wù)的調(diào)度。任務(wù)之間通信與同步。臨界區(qū)的代碼的處理。時間管理:時鐘節(jié)拍的處理。中斷服務(wù)程序的設(shè)計。

C/OS的初始化與啟動。

C/OS的多任務(wù)的運(yùn)行。C/OS-II的內(nèi)核結(jié)構(gòu)

C/OS-II中使用的數(shù)據(jù)類型typedefunsignedcharBOOLEAN;typedefunsignedcharINT8U;/*Unsigned8bitquantity*/typedefsignedcharINT8S;/*Signed8bitquantity*/typedefunsignedintINT16U;/*Unsigned16bitquantity*/typedefsignedintINT16S;/*Signed16bitquantity*/typedefunsignedlongINT32U;/*Unsigned32bitquantity*/typedefsignedlongINT32S;/*Signed32bitquantity*/typedeffloatFP32;/*Singleprecisionfloatingpoint*/typedefdoubleFP64;/*Doubleprecisionfloatingpoint*/typedefunsignedintOS_STK;/*Eachstackentryis16-bitwide*/typedefunsignedshortOS_CPU_SR;/*DefinesizeofCPUstatusregister(PSW=16bits)*/#defineBYTEINT8S/*Definedatatypesforbackwardcompatibility...*/#defineUBYTEINT8U/*...touC/OSV1.xx.Notactuallyneededfor...*/#defineWORDINT16S/*...uC/OS-II.*/#defineUWORDINT16U#defineLONGINT32S#defineULONGINT32U為了移植方便,在C/OS-II中重新定義一套新的數(shù)據(jù)類型。OS_CPU.h文件中描述了針對x86類型CPU的C語言中的這二種數(shù)據(jù)類型之間的關(guān)系:

第三節(jié)μC/OS-II的任務(wù)及其存儲結(jié)構(gòu)C/OS

–II的任務(wù)任務(wù)是一個無限循環(huán)。一個典型的例子:voidmytask(void*pdata){for(;;){dosomething;waiting;dosomething;}}C/OS

–II2.5版本支持64個任務(wù),每個任務(wù)一個特定的優(yōu)先級。優(yōu)先級越高,數(shù)字越小。系統(tǒng)占用了8個任務(wù),保留優(yōu)先級為0、1、2、3、OS_LOWEST_PRIO-3、OS_LOWEST_PRIO-2、OS_LOWEST_PRIO-1、OS_LOWEST_PRIO-0。

一個任務(wù)的例子voidTask1 (void*pdata){uint8err; pdata=pdata;

while(1) {OSSemPend(UART0_Sem,0,&err); //請求一個信號量UART_SendStr(“Task1isrunning!\r\n”); //通過串口在屏幕顯示OSTimeDly(OS_TICKS_PER_SEC); //延時OSSemPost(UART0_Sem); //本任務(wù)發(fā)送一個信號量 }}

任務(wù)存儲結(jié)構(gòu)任務(wù)控制塊前一個任務(wù)控制塊指針任務(wù)的代碼Voidmytask(void*pdata){….For(;;){….}}指向任務(wù)堆棧的指針后一個任務(wù)控制塊指針任務(wù)的優(yōu)先級任務(wù)堆棧指向任務(wù)的代碼

任務(wù)狀態(tài)

第四節(jié)任務(wù)控制塊(TCB)與任務(wù)堆棧任務(wù)控制塊OS_TCB是一個數(shù)據(jù)結(jié)構(gòu),保存該任務(wù)的相關(guān)參數(shù),包括任務(wù)堆棧指針,狀態(tài),優(yōu)先級,任務(wù)表位置,任務(wù)鏈表指針等。所有的任務(wù)控制塊分為兩條鏈表,空閑鏈表和使用鏈表。

μC/OS-II任務(wù)控制塊typedefstructos_tcb{OS_STK*OSTCBStkPtr;/*Pointertocurrenttopofstack*/#ifOS_TASK_CREATE_EXT_EN>0void*OSTCBExtPtr;/*PointertouserdefinabledataforTCBextension*/OS_STK*OSTCBStkBottom;/*Pointertobottomofstack*/INT32UOSTCBStkSize;/*Sizeoftaskstack(innumberofstackelements)*/INT16UOSTCBOpt;/*TaskoptionsaspassedbyOSTaskCreateExt()*/INT16UOSTCBId;/*TaskID(0..65535)*/#endifstructos_tcb*OSTCBNext;/*PointertonextTCBintheTCBlist*/structos_tcb*OSTCBPrev;/*PointertopreviousTCBintheTCBlist*/#if((OS_Q_EN>0)&&(OS_MAX_QS>0))||(OS_MBOX_EN>0)||(OS_SEM_EN>0)||(OS_MUTEX_EN>0)OS_EVENT*OSTCBEventPtr;/*Pointertoeventcontrolblock*/#endif#if((OS_Q_EN>0)&&(OS_MAX_QS>0))||(OS_MBOX_EN>0)void*OSTCBMsg;/*MessagereceivedfromOSMboxPost()orOSQPost()*/#endif

μC/OS-II任務(wù)控制塊#if(OS_VERSION>=251)&&(OS_FLAG_EN>0)&&(OS_MAX_FLAGS>0)#ifOS_TASK_DEL_EN>0OS_FLAG_NODE*OSTCBFlagNode;/*Pointertoeventflagnode*/#endifOS_FLAGSOSTCBFlagsRdy;/*Eventflagsthatmadetaskreadytorun*/#endifINT16UOSTCBDly;/*Nbrtickstodelaytaskor,timeoutwaitingforevent*/INT8UOSTCBStat;/*Taskstatus*/INT8UOSTCBPrio;/*Taskpriority(0==highest,63==lowest)*/INT8UOSTCBX;/*Bitpositioningroupcorrespondingtotaskpriority(0..7)*/INT8UOSTCBY;/*Indexintoreadytablecorrespondingtotaskpriority*/INT8UOSTCBBitX;/*Bitmasktoaccessbitpositioninreadytable*/INT8UOSTCBBitY;/*Bitmasktoaccessbitpositioninreadygroup*/#ifOS_TASK_DEL_EN>0BOOLEANOSTCBDelReq;/*Indicateswhetherataskneedstodeleteitself*/#endif}OS_TCB;

OSTCBStkPtr指向當(dāng)前任務(wù)堆棧頂?shù)闹羔極S_TASK_CREATE_EXT_EN用于控制是否允許擴(kuò)展任務(wù)控制塊。1-允許0-不允許OSTCBExtPtr指向任務(wù)控制塊擴(kuò)展部分的指針OSTCBStkBottom指向當(dāng)前任務(wù)堆棧底的指針OSTCBStkSize任務(wù)堆棧的長度OSTCBOpt當(dāng)允許擴(kuò)展任務(wù)控制塊時,OSTCBOpt代表OS_TASK_OPT_STK_CHK、OS_TASK_OPT_STK_CLR、OS_TASK_OPT_SAVE_FP中的一個,將此參數(shù)(分別為是否允許堆棧檢驗、清除,是否允許浮點運(yùn)算)傳給函數(shù)OSTaskCreateExt().OSTCBId//用于任務(wù)存儲的識別碼OSTCBNext//指向后一個任務(wù)控制塊OSTCBPrev//指向前一個任務(wù)控制塊OS_Q_EN//用于控制是否使用C/OS

–II中的消息隊列函數(shù)及其相關(guān)的數(shù)據(jù)結(jié)構(gòu)OS_MAX_QS//代表系統(tǒng)可以創(chuàng)建的消息隊列的最大數(shù)OS_MBOX_EN//用于控制是否使用C/OS

–II中的消息郵箱函數(shù)及其相關(guān)的數(shù)據(jù)結(jié)構(gòu)OSTCBEventPtr//指向事件控制塊的指針OSTCBMsg//指向傳遞給任務(wù)的消息的指針

OSTCBFLAGNode//指向事件標(biāo)志節(jié)點的指針OSTCBFlagRdy、OSTCBFlagNode//指向信號量集的任務(wù)進(jìn)入就緒態(tài)的事件標(biāo)志及指向信號量集等待任務(wù)鏈表節(jié)點指針OS_VERSION//系統(tǒng)版本號OS_FLAG_EN//用于控制是否使用所有事件標(biāo)志函數(shù)及其相關(guān)的數(shù)據(jù)結(jié)構(gòu)。為1使用,為0不使用。OS_MAX_FLAG//用戶程序中所需要的事件標(biāo)志最大數(shù)OS_TASK_DEL_EN//在C/OS

–II中是否使用OSTaskDel()函數(shù),為1使用,為0不使用。OSTCBDly//某任務(wù)允許等待事件發(fā)生的最多時鐘節(jié)拍數(shù)。OSTCBStat//任務(wù)當(dāng)前狀態(tài)標(biāo)志OSTCBPrio//任務(wù)的優(yōu)先級OSTCBX//用于快速訪問就緒表的數(shù)據(jù),對應(yīng)prio%8的值OSTCBY//用于快速訪問就緒表的數(shù)據(jù),對應(yīng)prio>>3的值。OSTCBBitX//用于快速訪問就緒表的數(shù)據(jù),等于OSTCBTbl[prio>>3]的值。OSTCBBitY//用于快速訪問就緒表的數(shù)據(jù),對應(yīng)OSMap[prio&0x07]的值,如果它為1則置OSRdyGrp的第Y位的值為1,Y=OSTCBY。OSTCBDelReg//請求刪除任務(wù)時用到的標(biāo)志

任務(wù)控制塊OS_TCB中幾個成員的算法OSTCBY=priority>>3;OSTCBBitY=OSMapTbl[priority>>3];OSTCBX=priority&0x07;OSTCBBitX=OSMapTbl[priority&0x07];

空任務(wù)列表所有的任務(wù)控制塊都被放置在任務(wù)控制塊列表數(shù)組OSTCBTbl[]中,系統(tǒng)初始化時,所有任務(wù)控制塊被鏈接成空任務(wù)控制塊的單向鏈表,任務(wù)建立后,空任務(wù)控制塊指針OSTCBFreeList指向的任務(wù)控制塊就賦給了該任務(wù),然后OSTCBFreeList的值調(diào)整為指向鏈表中的下一個空任務(wù)控制塊。

任務(wù)控制塊鏈表

任務(wù)的堆棧SP處理器OSTCBStkPtr創(chuàng)建任務(wù)時TaskStk任務(wù)運(yùn)行時任務(wù)創(chuàng)建時,把任務(wù)堆棧的棧頂?shù)刂焚x給OSTCBStkPtr。任務(wù)運(yùn)行時,OSTCBStkPtr賦給SP(堆棧棧頂指針寄存器)該任務(wù)運(yùn)行時,SP的值會發(fā)生變化。實際上任務(wù)的堆棧是用一個類型為OS_STK的數(shù)組:#defileTASK_STK_SIZE512OS_STKTeskStr[TASK_STK_SIZE];//這里并沒有確定棧頂?shù)奈恢?/p>

任務(wù)的堆棧低地址高地址堆棧增長的方向堆棧增長的方向增長方向為向下的堆棧OS_STK_GROWTH=1//為缺省值&TeskStr[TASK_STK_SIZE-1]指向棧頂增長方向為向上的堆棧OS_STK_GROWTH=0&TeskStr[0]指向棧頂(參考書中84頁)

臨界區(qū)臨界區(qū)是正在運(yùn)行的一段不可中斷的程序代碼。在進(jìn)入臨界區(qū)之前,要關(guān)一切允許中斷標(biāo)志。在退出臨界區(qū)之后,要立刻開啟一切允許中斷標(biāo)志。關(guān)中斷時間是實時內(nèi)核最重要的指標(biāo)之一;在實際應(yīng)用中,關(guān)中斷的時間很大程度中取決于微處理器的結(jié)構(gòu)和編譯器生成的代碼質(zhì)量;C/OS-II定義兩個宏開關(guān)中斷:OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()。至于如何實現(xiàn)這兩個宏,在移植過程中,對于不同的微處理器,采用不同的方法。這樣做是便于C/OS-II的移植;

C/OS-II中采用了3種開關(guān)中斷的方法OS_CRITICAL_METHOD==1用處理器指令關(guān)中斷,執(zhí)行OS_ENTER_CRITICAL(),開中斷執(zhí)行OS_EXIT_CRITICAL();OS_CRITICAL_METHOD==2實現(xiàn)OS_ENTER_CRITICAL()時,先在堆棧中保存中斷的開/關(guān)狀態(tài),然后再關(guān)中斷;實現(xiàn)OS_EXIT_CRITICAL()時,從堆棧中彈出原來中斷的開/關(guān)狀態(tài);OS_CRITICAL_METHOD==3把當(dāng)前處理器的狀態(tài)字保存在局部變量中(如OS_CPU_SR,關(guān)中斷時保存,開中斷時恢復(fù)

任務(wù)控制塊初始化函數(shù)主要做三件事:⑴從空任務(wù)鏈表取出一任務(wù)控制塊,填入相關(guān)數(shù)據(jù);⑵修改就緒表及OSTCBPrioTbl[prio]的值(OSTCBPrioTbl[prio]=ptcb

;⑶修改任務(wù)鏈表;INT8UOS_TCBInit(INT8Uprio,OS_STK*ptos,OS_STK*pbos,INT16Uid,INT32Ustk_size,void*pext,INT16Uopt){#ifOS_CRITICAL_METHOD==3/*AllocatestorageforCPUstatusregister*/OS_CPU_SRcpu_sr;#endifOS_TCB*ptcb;OS_ENTER_CRITICAL();

ptcb=OSTCBFreeList;/*GetafreeTCBfromthefreeTCBlist*/

if(ptcb!=(OS_TCB*)0){OSTCBFreeList=ptcb->OSTCBNext;/*UpdatepointertofreeTCBlist*/OS_EXIT_CRITICAL();ptcb->OSTCBStkPtr=ptos;/*LoadStackpointerinTCB*/ptcb->OSTCBPrio=(INT8U)prio;/*LoadtaskpriorityintoTCB*/ptcb->OSTCBStat=OS_STAT_RDY;/*Taskisreadytorun*/ptcb->OSTCBDly=0;/*Taskisnotdelayed*/

任務(wù)控制塊初始化函數(shù)#ifOS_TASK_CREATE_EXT_EN>0ptcb->OSTCBExtPtr=pext;/*StorepointertoTCBextension*/ptcb->OSTCBStkSize=stk_size;/*Storestacksize*/ptcb->OSTCBStkBottom=pbos;/*Storepointertobottomofstack*/ptcb->OSTCBOpt=opt;/*Storetaskoptions*/ptcb->OSTCBId=id;/*StoretaskID*/#elsepext=pext;/*Preventcompilerwarningifnotused*/stk_size=stk_size;pbos=pbos;opt=opt;id=id;#endif#ifOS_TASK_DEL_EN>0ptcb->OSTCBDelReq=OS_NO_ERR;//OS_NO_ERR為0X00#endif

ptcb->OSTCBY=prio>>3;/*Pre-computeX,Y,BitXandBitY*/ptcb->OSTCBBitY=OSMapTbl[ptcb->OSTCBY];ptcb->OSTCBX=prio&0x07;ptcb->OSTCBBitX=OSMapTbl[ptcb->OSTCBX];

任務(wù)控制塊初始化函數(shù)#ifOS_EVENT_EN>0ptcb->OSTCBEventPtr=(OS_EVENT*)0;/*Taskisnotpendingonanevent*/#endif#if(OS_VERSION>=251)&&(OS_FLAG_EN>0)&&(OS_MAX_FLAGS>0)&&(OS_TASK_DEL_EN>0)ptcb->OSTCBFlagNode=(OS_FLAG_NODE*)0;/*Taskisnotpendingonaneventflag*/#endif#if(OS_MBOX_EN>0)||((OS_Q_EN>0)&&(OS_MAX_QS>0))ptcb->OSTCBMsg=(void*)0;/*Nomessagereceived*/#endif#ifOS_VERSION>=204OSTCBInitHook(ptcb);#endifOSTaskCreateHook(ptcb);/*Calluserdefinedhook*/

OS_ENTER_CRITICAL();

OSTCBPrioTbl[prio]=ptcb;

任務(wù)控制塊初始化函數(shù)

ptcb->OSTCBNext=OSTCBList;/*LinkintoTCBchain*/ptcb->OSTCBPrev=(OS_TCB*)0;if(OSTCBList!=(OS_TCB*)0){OSTCBList->OSTCBPrev=ptcb;}OSTCBList=ptcb;//插入任務(wù)鏈表的首部OSRdyGrp|=ptcb->OSTCBBitY;/*Maketaskreadytorun*/OSRdyTbl[ptcb->OSTCBY]|=ptcb->OSTCBBitX;OS_EXIT_CRITICAL();return(OS_NO_ERR);}OS_EXIT_CRITICAL();return(OS_NO_MORE_TCB);}對于一般方式創(chuàng)建任務(wù):OS_TCBInit(prio,psp,(OS_STK*)0,0,0,(void*)0,0);對于擴(kuò)展方式創(chuàng)建任務(wù):OS_TCBInit(prio,psp,pbos,id,stk_size,pext,opt);

第五節(jié)系統(tǒng)的任務(wù)、空閑任務(wù)、統(tǒng)計任務(wù)系統(tǒng)任務(wù)μC/OS-II操作系統(tǒng)本身占據(jù)64任務(wù)中的8個??臻e任務(wù)OSTaskIdle()這是一個系統(tǒng)任務(wù)。它的優(yōu)先級最低:OS_LOWEST_PRIO-0。統(tǒng)計任務(wù)OSTaskStat()這也是一個系統(tǒng)任務(wù)。它的優(yōu)先級次低:OS_LOWEST_PRIO-1。

空閑任務(wù)OSTaskIdle()voidOSTaskIdle(void*pdata){pdata=pdata;for(;;){OS_ENTER_CRITICAL();OSIdleCtr++;//空閑任務(wù)計數(shù)器OS_EXIT_CRITICAL();}}

第三講任務(wù)管理創(chuàng)建任務(wù)就緒任務(wù)的管理任務(wù)的掛起和恢復(fù)其它任務(wù)管理函數(shù)任務(wù)調(diào)度任務(wù)的切換

第一節(jié)

創(chuàng)建任務(wù)UseoneoftwoservicesINT8UOSTaskCreate(void(*task)(task*pd),void*pdata,OS_STK*ptos,INT8Uprio)INT8UOSTaskCreateExt(TaskCreate(void(*task)(task*pd),void*pdata,OS_STK*ptos,INT8Uprio,INT16Uid,OS_STK*pbos,INT32Ustk_size,void*pext,INT16Uopt)其中:id是一個特殊標(biāo)志,為C/OS-II的擴(kuò)展而設(shè)置。可與prio相同。pext指向用戶附加的數(shù)據(jù)域的指針。為C/OS-II的擴(kuò)展而設(shè)置。opt設(shè)置附加選項。

創(chuàng)建一任務(wù)檢查優(yōu)先級的合法性在OSTCBPrioTbl[]注冊堆棧初始化取出一空任務(wù)控制塊向任務(wù)控制塊寫數(shù)據(jù)有沒空任務(wù)控制塊創(chuàng)建失敗返回創(chuàng)建失敗返回執(zhí)行一次調(diào)度創(chuàng)建成功返回正在執(zhí)行過程中合法不合法沒有有沒有正在“正在執(zhí)行過程中”是指已有任務(wù)在CPU中運(yùn)行。例如本函數(shù)的執(zhí)行正是由某個正在運(yùn)行的任務(wù)需創(chuàng)建一個新任務(wù),此時必須引發(fā)一次新的調(diào)度。由于調(diào)度可能新任務(wù)立刻獲得CPU的運(yùn)行權(quán)。但是,在一開始(OSStart()之前),沒有任何任務(wù)開始運(yùn)行,是不會引發(fā)一次新的調(diào)度。本任務(wù)的任務(wù)控制塊初始化

建立任務(wù),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)//該任務(wù)是否已存在OSTCBPrioTbl[prio]=(OS_TCB*)1;(3)OS_EXIT_CRITICAL();(4)psp=(void*)OSTaskStkInit(task,pdata,ptos,0);err=OSTCBInit(prio,psp,(void*)0,0,0,(void*)0,0);if(err==OS_NO_ERR){ OS_ENTER_CRITICAL();

OSTaskCtr++; OSTaskCreateHook(OSTCBPrioTbl[prio]); OS_EXIT_CRITICAL();if(OSRunning){//如果本任務(wù)是正在執(zhí)行的任務(wù)創(chuàng)建的 OSSched(); }}else{//任務(wù)控制塊初始化失敗OS_ENTER_CRITICAL();OSTCBPrioTbl[prio]=(OS_TCB*)0; OS_EXIT_CRITICAL();}return(err);}else{//沒有空閑任務(wù)控制塊

OS_EXIT_CRITICAL();return(OS_PRIO_EXIST);}}

Void(*task)(Void*pd)//指向任務(wù)的指針Void*pdata//傳遞給任務(wù)的指針OS_STK*ptos//指向任務(wù)堆棧棧頂?shù)闹羔業(yè)NT8Uprio//任務(wù)的優(yōu)先級If(prio>OS_LOWST_PRIO)//判斷給出的優(yōu)先級的合法性:給出的優(yōu)先級不能低于空閑任務(wù)的優(yōu)先級。OSTCBPrioTbl[]//保存所有(64)個優(yōu)先級的任務(wù)所指向的任務(wù)控制塊的指針,如果某優(yōu)先級(Prio)的任務(wù)尚未建立,則OSTCBPrioTbl[Prio]==(OS_TCB*)即指針為空。OSTCBPrioTbl[prio]=(OS_TCB*)1//只是給一個非空的指針,說明優(yōu)先級(Prio)的任務(wù)尚已建立,保留該優(yōu)先級。任務(wù)堆棧初始化OSTaskStkInit()過程中將指向任務(wù)代碼指針、傳遞給該任務(wù)的其它參數(shù)存入堆棧,并返回棧頂指針psp。完成堆棧的建立。任務(wù)控制塊初始化OSTCBInit()過程首先將空任務(wù)鏈表的酋指針OSTCBFreeList所指向的任務(wù)控制塊賦給OSTCBPrioTbl[prio],并將該任務(wù)控制塊加入任務(wù)鏈表。把相應(yīng)參數(shù)寫入任務(wù)控制塊,同時在就緒任務(wù)表中登記。返回任務(wù)控制塊初始化是否成功的標(biāo)志。如果成功,任務(wù)計數(shù)器加1。同時判斷該任務(wù)的創(chuàng)建是在某一正在執(zhí)行過程中,則要執(zhí)行一次調(diào)度。如果創(chuàng)建的任務(wù)優(yōu)先級高,則執(zhí)行該任務(wù)。

創(chuàng)建任務(wù)的一般方法voidmain(void){OSInit();/*初始化uC/OS-II (1)*/

...OSTaskCreate(TaskStart,s_M,&MyTaskStk[TASK_STK_SIZE-1],0);OSStart();/*開始多任務(wù)調(diào)度 (3)*/}voidTaskStart(void*pdata){/*安裝并啟動uC/OS-II的時鐘節(jié)拍 (4)*/OSStatInit();/*初始化統(tǒng)計任務(wù) (5)*//*創(chuàng)建用戶應(yīng)用程序任務(wù) */for(;;){/*這里是TaskStart()的代碼! */}}

例5-2#include“includes.h”#defineTASK_STK_SIZE512//任務(wù)堆棧的長度OS_STKMyTask[TASK_STK_SIZE];//定義任務(wù)堆棧區(qū)INT16Skey; //用于退出μC/OS-II任務(wù)的鍵INT8Ux=0,y=0; //字符顯示的位置VoidMyTask(void*data);//聲明一個任務(wù)Voidmain(void){char*s_M=“M”;//定義要顯示的字符OSInit(); //初始化μC/OS-IIPC_DOSSaveReturn(); //保存DOS環(huán)境PC_VectSet(ucos,osctxSw);//安裝μC/OS-II任務(wù)切換中斷向量

OSTaskCreate(MyTask,//創(chuàng)建任務(wù)MyTasks_M, //給任務(wù)傳遞參數(shù)&MyTaskStk[TASK_STK_SIZE-1],//設(shè)置任務(wù)堆棧棧頂指針0); //設(shè)任務(wù)MyTask的優(yōu)先級為0

}//endofmainVoidMyTask(void*pdata){#ifOS_CRITICAL_METHOD==3//如果采用第三種開關(guān)中斷方式OS_CPU_SRcpu_sr; //則定義一個寄存器變量cpu_sr#endifptata=ptata; OS_ENTER_CRITICAL(); //關(guān)中斷PC_VectSet(0x08,OSTickISR); //安裝μC/OS-II時鐘中斷向量

PC_SetTickRate(OS_TICKS_PER_SEC);//設(shè)置μC/OS-II時鐘頻率OS_EXIT_CRITICAL(); //開中斷OSStatInit(); //初始化μC/OS-II的統(tǒng)計任務(wù)for(;;){if(x>10){x=0;y+=2;}

PC_DispChar(x,y,*(chat*)pdata,DISP_BGND_BLACK+DISP_FGND_WHITE};x+=1;if(PC_GetKey(&key)==TRUE){if(key==0x1B){PC_DOSReturn();//返回DOS}}

OSTimeDlyHMSM(0,0,1,0);//等待1s}}

第二節(jié)

就緒任務(wù)的管理就緒任務(wù)表根據(jù)就緒表確定最高優(yōu)先級任務(wù)就緒表的特點根據(jù)優(yōu)先級找到任務(wù)在就緒任務(wù)表中的位置使任務(wù)進(jìn)入就緒態(tài)使任務(wù)脫離就緒態(tài)采用查表法確定就緒任務(wù)隊列中最高優(yōu)先級任務(wù)優(yōu)先級判定表

就緒任務(wù)表每個就緒的任務(wù)都放入就緒表中(readylist)中,就緒表有兩個變量:OSRdyGrp、OSRdyTbl[]OSRdyGrp1207654300XXXYYY任務(wù)優(yōu)先級2017654310891514131211181617232221201926242531302928273432333938373635424041474645444350484955545352515856576362616059[0][1][2][3][4][5][6][7]OSRdyTbl[7]XY優(yōu)先級最低任務(wù)(空閑任務(wù))優(yōu)先級最高任務(wù)任務(wù)優(yōu)先級號

任務(wù)就緒表的特點任務(wù)就緒表是用INT8U類型的數(shù)組OSRdyTbl[]表示。OSRdyTbl[]中每一個元素OSRdyTbl[y]可表達(dá)八個任務(wù)的就緒狀態(tài):1為就緒態(tài);0為不就緒態(tài)。長度為8的數(shù)組OSRdyTbl[]可表達(dá)64個任務(wù)的就緒狀態(tài)。每一個元素OSRdyTbl[y]所表達(dá)的八個任務(wù)為就緒任務(wù)組。優(yōu)先級prio的最大值為63,可表示為00111111B。任何任務(wù)的優(yōu)先級prio低6位中的前三位的值y表示該任務(wù)的就緒狀態(tài),在數(shù)組OSRdyTbl[y]的元素得到表示。如果該任務(wù)就緒,則INT8U類型的變量OSRdyGrp的相對應(yīng)的第y位為1。低6位中的后三位的值x,表示該任務(wù)的就緒狀態(tài)在數(shù)組OSRdyTbl[y]元素的第x位為1。變量OSRdyGrp反映了整個任務(wù)就緒情況。任務(wù)就緒表中的任務(wù)是按優(yōu)先級排列。數(shù)學(xué)表示:優(yōu)先級為prio的任務(wù)的就緒狀態(tài)在數(shù)組OSRdyTbl[prio>>3]的第x位。x=prio%8或x=prio&0x07,后者處理速度更快。通過數(shù)組OSRdyTbl[]、OSRdyGrp變量可管理64個就緒任務(wù)。利用任務(wù)就緒表要解決如下幾個問題:創(chuàng)建任務(wù)時,要在就緒表中登記,在對應(yīng)位置,置1。刪除任務(wù)時,要在就緒表中找到對應(yīng)位置,置0。在任務(wù)就緒表中,找到優(yōu)先級最高的任務(wù)。且保證服務(wù)時間相同。

根據(jù)優(yōu)先級找到任務(wù)在就緒任務(wù)表中的位置(1)假設(shè)優(yōu)先級為12的任務(wù)進(jìn)入就緒狀態(tài),12=0000

1100b,則OSRdyTbl[1]的第4位置1,且OSRdyGrp的第1位置1,相應(yīng)的數(shù)學(xué)表達(dá)式為:

OSRdyGrp|=00000010或者OSRdyGrp|=0x02;OSRdyTbl[1]|=00010000或者OSRdyTbl[1]|=0x10;而優(yōu)先級為21的任務(wù)就緒21=0001

0101b,則OSRdyTbl[2]的第5位置1,且OSRdyGrp的第2位置1,相應(yīng)的數(shù)學(xué)表達(dá)式為:

OSRdyGrp|=00000100或者OSRdyGrp|=0x04;;OSRdyTbl[2]|=00100000或者OSRdyTbl[2]|=0x20;;在上述表達(dá)式中,類似0x02、0x10、0x04、0x20如何從任務(wù)的優(yōu)先級數(shù)prio導(dǎo)出。為此定義了一個INT8U類型的數(shù)組OSMapTbl[]。通過它可以快速找到就緒任務(wù)在數(shù)組OSRdyTbl[]元素的位置。數(shù)組OSMapTbl[]是一個特殊的數(shù)組

根據(jù)優(yōu)先級找到任務(wù)在就緒任務(wù)表中的位置(2)從上面的計算我們可以得到:若OSRdyGrp及OSRdyBbl[]的第n位置1,則應(yīng)該把OSRdyGrp及OSRdyBbl[]的值與2n相或。uC/OS中,把2n的n=0-7的8個值先計算好存在數(shù)組OSMapTbl[]中,也就是:

OSMapTbl[0]=20=0x01(00000001)OSMapTbl[1]=21=0x02(00000010)

……OSMapTbl[7]=27=0x80(10000000)為什么我們要采用數(shù)組OSMapTbl[]?事實上,只要給出數(shù)組元素的下標(biāo)值,我們就可找到數(shù)組元素的值。不論下標(biāo)值的大小,所需時間都相等,而且時間可預(yù)知。算法如下:數(shù)組元素的所在的位置:數(shù)組的首地址+下標(biāo)值×數(shù)組元素所占的字節(jié)數(shù)。優(yōu)點是,符合實時操作系統(tǒng)的要求。缺點是,空間耗費(fèi)更大。

使任務(wù)進(jìn)入就緒態(tài)一般情況下,如果prio是任務(wù)的優(yōu)先級,也是任務(wù)的識別號,則將任務(wù)放入就緒表,即使任務(wù)進(jìn)入就緒態(tài)的方法是:OSRdyGrp|=OSMapTbl[prio>>3];(1)OSRdyTbl[prio>>3]|=OSMapTbl[prio&0x07];(2)例如,假設(shè)優(yōu)先級為12——1100bOSRdyGrp|=OSMapTbl[1] ; //(00000010)OSRdyTbl[1]|=OSMapTbl[4] ; //(00010000)為了減少在調(diào)度過程中,反復(fù)計算prio>>3、prio&0x07和OSMapTbl[prio>>3]和OSMapTbl[prio&0x07]的值,設(shè)置如下成員變量:ptcb->OSTCBY=prio>>3;ptcb->OSTCBBitY=OSMapTbl[ptcb->OSTCBY];ptcb->OSTCBX=prio&0x07;ptcb->OSTCBBitX=OSMapTbl[ptcb->OSTCBX];這樣(1)、(2)式就可寫成:OSRdyGrp|=ptcb->OSTCBBitY;(1)OSRdyTbl[ptcb->OSTCBY]|=ptcb->OSTCBBitX;(2)

使任務(wù)脫離就緒態(tài)使任務(wù)脫離就緒態(tài)就是將任務(wù)就緒表OSRdyTbl[prio>>3]相應(yīng)元素的相應(yīng)位清零。只需OSRdyTbl[prio>>3]&=

OSMapTbl[prio&0x07]而且當(dāng)OSRdyTbl[prio>>3]中的所有位都為零時,即全組任務(wù)中沒有一個進(jìn)入就緒態(tài)時,OSRdyGrp的相應(yīng)位才為零。if((OSRdyTbl[prio>>3]&=

OSMapTbl[prio&0x07])==0)OSRdyGrp&=

OSMapTbl[prio>>3];(僅對該位置零)否則任務(wù)組中還有進(jìn)入就緒態(tài)的任務(wù)

采用查表法確定就緒任務(wù)隊列中最高優(yōu)先級任務(wù)有多種方法可以從多個就緒任務(wù)中找出優(yōu)先級最高的任務(wù),但是為保證查找的快速和時間到預(yù)測。作者采用查表法。從就緒任務(wù)表中可看出,首先從OSRdyGrp可求出,優(yōu)先級最高的任務(wù)一定位于其中從右至左,首個不為零的那一位所在的行Y。然后依據(jù)OSRdyTbl[Y],優(yōu)先級最高的任務(wù)一定位于其中從右至左,首個不為零的那一位所在的列X。

根據(jù)這個原理,我們設(shè)計了優(yōu)先級查找表OSUnMapTbl[],實現(xiàn)高速查找。優(yōu)先級查找表是一個數(shù)組。根據(jù)數(shù)組的首地址和下標(biāo)值,可以很快找到該元素的值。所費(fèi)的時間是相同的。

INT8UconstOSUnMapTbl[]={0,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0};優(yōu)先級判定表OSUnMapTbl[256]舉例:

如OSRdyGrp的值為01101000B,即0X68(104),則查得OSUnMapTbl[OSRdyGrp]的值是3,它相應(yīng)于OSRdyGrp中的第3位置1;如OSRdyTbl[3]的值是11100100B,即0XE4(228),則查OSUnMapTbl[OSRdyTbl[3]]的值是2,則進(jìn)入就緒態(tài)的最高任務(wù)優(yōu)先級Prio=3*8+2=26

優(yōu)先級判定表OSUnMapTbl[]是如何產(chǎn)生的我們就不討論。但同學(xué)們可以想一想。

采用查表法確定就緒任務(wù)隊列中最高優(yōu)先級任務(wù)查表法具有確定的時間,增加了系統(tǒng)的可預(yù)測性,uC/OS中所有的系統(tǒng)調(diào)用時間都是確定的High3=OSUnMapTbl[OSRdyGrp];//獲得優(yōu)先級高三位Low3=OSUnMapTbl[OSRdyTbl[High3]];//獲得優(yōu)先級低三位Prio=(Hign3<<3)+Low3;//Prio=Hign*8+LowOSRdyGrp1207654300XXXYYY任務(wù)優(yōu)先級2017654310891514131211181617232221201926242531302928273432333938373635424041474645444350484955545352515856576362616059[0][1][2][3][4][5][6][7]OSRdyTbl[7]XY

第三節(jié)任務(wù)的掛起INT8UOSTaskSuspend(INT8Uprio)Prio是空閑任務(wù)?標(biāo)志self=TRUE?取消任務(wù)的就緒狀態(tài),并控制塊中進(jìn)行記錄返回OS_NO_ERR標(biāo)志self=FALSE返回OS_PRIO_INVALID返回OS_TASK_SUSPEND_IDLE指針非空?返回OS_TASK_SUPEND_PRIO進(jìn)入Prio是合法的優(yōu)先級?prio=OXFF(OS_PRIO_SELF)?標(biāo)志self=TRUE,并從OSTCBCur中取出prio調(diào)用任務(wù)調(diào)度器OS_Sched()YESNONONOYESYESNOYESNOYES當(dāng)前任務(wù)?NOYES根據(jù)prio取任務(wù)TCB的指針掛起態(tài):OS_STAT_SUSPEND。被掛起的任務(wù)可以是一個正在等待的任務(wù):ptcb->OSTCBStat|=OS_STAT_SUSPEND;

第四節(jié)恢復(fù)任務(wù)INT8UOSTaskResume(INT8Uprio)取消任務(wù)在控制塊中的掛起的記錄,置就緒態(tài)返回OS_NO_ERR返回OS_TASK_NOT_SUSPEND返回OS_TASK_RESUME_PRIO返回OS_PRIO_INVALID進(jìn)入prio=OXFF?調(diào)用任務(wù)調(diào)度器OS_Sched()NONONOYESYESYESPrio是合法的優(yōu)先級?取任務(wù)TCB的指針任務(wù)存在&&是被掛起的任務(wù)&&等待時間為0指針!=NULL掛起的任務(wù),只能用本函數(shù)恢復(fù)。

第五節(jié)其他任務(wù)管理函數(shù)任務(wù)的優(yōu)先級的修改INT8UOSTaskChangPrio( INT8Uoldprio,//任務(wù)原來的優(yōu)先級 INT8Unewprio//任務(wù)新的優(yōu)先級 )查詢?nèi)蝿?wù) INT8UOSTaskQuery( INT8Uprio , //待查詢?nèi)蝿?wù)的優(yōu)先級 OS_TCB*pdata //儲存任務(wù)信息的結(jié)構(gòu) )任務(wù)的刪除 INT8UOSTaskDel(INT8Uprio)//參數(shù)為刪除任務(wù)的優(yōu)先級

任務(wù)的刪除任務(wù)的刪除可以刪除:任務(wù)自已,參數(shù)為OS_PRIO_SELF.將其它任務(wù)刪除,參數(shù)為INT8Uprio。任務(wù)刪除函數(shù)OSTaskDel(INT8Uprio)。如果參數(shù)為OS_PRIO_SELF,則從當(dāng)前任務(wù)塊中找出prio。任務(wù)的刪除要做四件事:從任務(wù)控制塊鏈表中刪除對應(yīng)該優(yōu)先級的任務(wù)控制塊。將對應(yīng)該優(yōu)先級的任務(wù)控制塊,加到空任務(wù)控制塊鏈表。在就緒表中,把對應(yīng)該優(yōu)先級的任務(wù)的就緒狀態(tài)位置0。執(zhí)行一次調(diào)度。為了保護(hù)資源不流失,在實應(yīng)用中不可直接調(diào)用此函數(shù),將任務(wù)刪除。必須由另一個任務(wù)先調(diào)用任務(wù)刪除請求函數(shù)申請刪除該任務(wù)。請求成功后,該任務(wù)的OS_TCB的成員OSTCBDelReq值為OS_TASK_DEL_REQ。而該任務(wù)同樣不斷調(diào)用任務(wù)刪除請求函數(shù),其參數(shù)為OS_PRIO_SELF,當(dāng)檢測到返回值為OS_TASK_DEL_REQ時,該任務(wù)要先釋放資源,后調(diào)用任務(wù)刪除函數(shù)刪除該任務(wù)。

任務(wù)的刪除請求OSTaskDelReq()任務(wù)的刪除請求OSTaskDelReq()有兩種正常執(zhí)行結(jié)果:⑴當(dāng)優(yōu)先級不為OS_PRIO_SELF時,返回值為OS_NO_ERR,且置OS_TCB中的成員變量OSTCBDelReq的值為OS_TASK_DEL_REQ⑵當(dāng)優(yōu)先級為OS_PRIO_SELF時,返回值為OS_TCB中的成員變量OSTCBDelReq的值整個執(zhí)行過程如圖所示:

任務(wù)的刪除請求OSTaskDelReq()prio是空閑任務(wù)?prio是合法的優(yōu)先級?prio=OS_PRIO_SELF?prio任務(wù)的TCB不存在?進(jìn)入返回OS_TASK_NOT_EXIST返回被刪除任務(wù)的OS_TCB的成員OSTCBDelReq的值置prio任務(wù)OS_TCB的OSTCBDelReq的值為OS_TASK_DEL_REQ返回OS_NO_ERR返回OS_PRIO_INVALID返回OS_TASK_IDLE_PRIOYesYesYesYesNoNoNoNo

請求刪除其它任務(wù)的任務(wù)代碼VoidRequestorTask(void*pdata){INT8Uerr;pdata=pdatafor(;;){/*應(yīng)用程序代碼*/if(任務(wù)‘TaskToBeDelected()’是需要刪除){//while(OSTaskDelReq(TASK_TO_DEL_PRIO)!=OS_TASK_NOT_EXIST)OSTimeDly(1);}}/*應(yīng)用程序代碼*/}這里TASK_TO_DEL_PRIO是需要刪除的任務(wù)TaskToBeDelected的優(yōu)先級。

需要刪除自已的任務(wù)VoidTaskToBeDeleted(void*pdata){INT8Uerr;pdata=pdatafor(;;){/*應(yīng)用程序代碼*/if(OSTaskDelReq(OS_PRIO_SELF)==OS_TASK_DEL_REQ)釋放所有占用的資源;釋放所有動態(tài)內(nèi)存;OSTaskDel(OS_PRIO_SELE);}else{/*應(yīng)用程序代碼*/}}該任務(wù)是別的任務(wù)請求刪除的。所有的刪除都是要允許的,即滿足:OS_TASK_DEL_EN>0。

第六節(jié)任務(wù)級的任務(wù)調(diào)度—OS_Sched按照某種規(guī)則選擇運(yùn)行的任務(wù)叫調(diào)度。讓CPU中止當(dāng)前運(yùn)行的任務(wù),轉(zhuǎn)而去運(yùn)行另一任務(wù)叫切換。

C/OS是占先式實時多任務(wù)內(nèi)核,優(yōu)先級最高的任務(wù)一旦準(zhǔn)備就緒,則擁有CPU的所有權(quán)開始投入運(yùn)行。

C/OS中不支持時間片輪轉(zhuǎn)法,每個任務(wù)的優(yōu)先級要求不一樣且是唯一的,所以任務(wù)調(diào)度的工作就是:查找準(zhǔn)備就緒的最高優(yōu)先級的任務(wù)并進(jìn)行上下文切換。

C/OS任務(wù)調(diào)度所花的時間為常數(shù),與應(yīng)用程序中建立的任務(wù)數(shù)無關(guān)。

任務(wù)調(diào)度voidOS_Sched(void){INT8Uy;#ifOS_CRITICAL_METHOD==3OS_CPU_SRCPU_sr#endifOS_ENTER_CRITICAL();if((OSLockNesting=0)&&(OSIntNesting=0)){ y=OSUnMapTbl[OSRdyGrp]; OSPrioHighRdy=(INT8U)((y<<3)+OSUnMapTbl[OSRdyTbl[y]])if(OSPrioHighRdy!=

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論