uCOS-II的移植及使用_第1頁(yè)
uCOS-II的移植及使用_第2頁(yè)
uCOS-II的移植及使用_第3頁(yè)
uCOS-II的移植及使用_第4頁(yè)
uCOS-II的移植及使用_第5頁(yè)
已閱讀5頁(yè),還剩145頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

uCOS-II的移植及使用報(bào)告人:日期:2016.1.181425uC/OS-II的任務(wù)3uC/OS-II的移植uC/OS-II同步與通信uC/OS-II概述uC/OS-III簡(jiǎn)介目錄uC/OS-II概述C/OS——MicroControllerOS,微控制器操作系統(tǒng)

美國(guó)人JeanLabrosse1992年完成應(yīng)用面覆蓋了諸多領(lǐng)域,如照相機(jī)、醫(yī)療器械、音響設(shè)備、發(fā)動(dòng)機(jī)控制、高速公路電話系統(tǒng)、自動(dòng)提款機(jī)等1998年出C/OS-II,目前的版本C/OS-IIV2.912000年,得到美國(guó)航空管理局(FAA)的認(rèn)證,可以用于飛行器中網(wǎng)站uC/OS-II概述-性能特點(diǎn)源代碼公開(kāi)可移植(Portable)大部分代碼用ANSIC寫(xiě),與處理器無(wú)關(guān),移植時(shí)不需修改少量與微處理器硬件相關(guān)的部分用C與匯編編寫(xiě),移植時(shí)需修改:OS_CPU.H//與硬件相關(guān),移植時(shí)需修改OS_CPU_A.ASM//集中了所有與處理器相關(guān)的匯編語(yǔ)言代碼OS_CPU.C//集中了所有與處理器相關(guān)的匯編語(yǔ)言代碼uC/OS-II概述-性能特點(diǎn)可裁剪(Scalable)可以只使用

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

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

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

C/OS-II所需的存儲(chǔ)器空間(RAM和ROM)??杉舨眯酝ㄟ^(guò)條件編譯實(shí)現(xiàn)。uC/OS-II概述-性能特點(diǎn)可剝奪性(Preemptive)與可確定性內(nèi)核可剝奪、函數(shù)調(diào)用或系統(tǒng)服務(wù)的執(zhí)行時(shí)間具有可確定性,是硬實(shí)時(shí)操作系統(tǒng)。支持多任務(wù)C/OS-II可以管理255個(gè)任務(wù)任務(wù)棧每個(gè)任務(wù)有自己?jiǎn)为?dú)的棧,

C/OS-II允許每個(gè)任務(wù)有不同的??臻g,以便壓低應(yīng)用程序?qū)AM的需求。uC/OS-II概述-性能特點(diǎn)系統(tǒng)服務(wù)C/OS-II提供很多系統(tǒng)服務(wù),例如郵箱、消息隊(duì)列、信號(hào)量、塊大小固定的內(nèi)存的申請(qǐng)與釋放、時(shí)間相關(guān)函數(shù)等。中斷管理中斷可以使正在執(zhí)行的任務(wù)暫時(shí)掛起,如果優(yōu)先級(jí)更高的任務(wù)被該中斷喚醒,則高優(yōu)先級(jí)的任務(wù)在中斷嵌套全部退出后立即執(zhí)行,中斷嵌套層數(shù)可達(dá)255層。uC/OS-II概述--文件結(jié)構(gòu)體系結(jié)構(gòu)1425uC/OS-II的任務(wù)3uC/OS-II的移植uC/OS-II同步與通信uC/OS-II概述uC/OS-III簡(jiǎn)介目錄uC/OS-II的任務(wù)2.1任務(wù)組成部分2.2任務(wù)的結(jié)構(gòu)2.3任務(wù)存儲(chǔ)結(jié)構(gòu)2.4任務(wù)狀態(tài)2.5任務(wù)優(yōu)先級(jí)2.6任務(wù)就緒表及任務(wù)調(diào)度2.7任務(wù)操作2.8uC/OS-II的初始化一個(gè)完整的任務(wù)應(yīng)該有如下三部分:任務(wù)代碼(程序)任務(wù)的私有堆棧(用以保護(hù)運(yùn)行環(huán)境)任務(wù)控制塊(提供私有堆棧也是虛擬處理器的位置)2.1uC/OS-II的任務(wù)—組成前一個(gè)任務(wù)控制塊的指針后一個(gè)任務(wù)控制塊的指針指向任務(wù)的指針指向任務(wù)堆棧的指針任務(wù)的優(yōu)先級(jí)別……voidmytask(void*pdata){……for(;;){……}}

任務(wù)的代碼

任務(wù)控制塊……

任務(wù)堆棧

任務(wù)圖2-4任務(wù)的組成從應(yīng)用程序設(shè)計(jì)的角度來(lái)看,任務(wù)就是一個(gè)線程。就是一個(gè)用來(lái)解決用戶問(wèn)題的C語(yǔ)言函數(shù)和與之相關(guān)聯(lián)的一些數(shù)據(jù)結(jié)構(gòu)而構(gòu)成的一個(gè)實(shí)體從任務(wù)存儲(chǔ)結(jié)構(gòu)來(lái)看,由三部分構(gòu)成:任務(wù)程序代碼、任務(wù)堆棧和任務(wù)控制塊。任務(wù)控制塊用來(lái)保存任務(wù)屬性,任務(wù)堆棧用來(lái)保存任務(wù)工作環(huán)境,任務(wù)程序代碼是任務(wù)的執(zhí)行部分2.1uC/OS-II的任務(wù)—組成uCOS中的任務(wù)是一個(gè)線程,其代碼通常是一個(gè)無(wú)限循環(huán)結(jié)構(gòu)/超循環(huán)結(jié)構(gòu),看起來(lái)像其它C函數(shù)一樣。2.1.1uC/OS-II的任務(wù)—代碼結(jié)構(gòu)voidMyTask(void*pdata) { for(;;) {

可以被中斷的任務(wù)代碼;

OS_ENTER_CRITICAL(); //進(jìn)入臨階段(關(guān)中斷) 不可以被中斷的任務(wù)代碼;

OS_EXIT_CRITICAL(); //退出臨階段(開(kāi)中斷)

可以被中斷的任務(wù)代碼;

}}根據(jù)嵌入式系統(tǒng)任務(wù)的工作特點(diǎn),任務(wù)的執(zhí)行代碼通常是一個(gè)無(wú)限循環(huán)結(jié)構(gòu),并且在這個(gè)循環(huán)中可以響應(yīng)中斷,這種結(jié)構(gòu)也叫超循環(huán)結(jié)構(gòu)。為了有效的對(duì)中斷進(jìn)行控制,在任務(wù)的代碼里可使用UC/OS-II定義的宏OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()來(lái)控制何時(shí)響應(yīng)中斷,何時(shí)屏蔽中斷。在運(yùn)行這兩個(gè)宏之間的代碼時(shí)是不會(huì)響應(yīng)中斷的,這種受保護(hù)的代碼段叫臨界段。一旦任務(wù)建立,一個(gè)任務(wù)控制塊OS_TCB就被賦值。任務(wù)控制塊是一個(gè)數(shù)據(jù)結(jié)構(gòu),保存該任務(wù)的相關(guān)參數(shù),包括任務(wù)堆棧指針,任務(wù)的當(dāng)前狀態(tài),任務(wù)的優(yōu)先級(jí)等。任務(wù)CPU使用權(quán)被剝奪時(shí),TCB保存該時(shí)刻任務(wù)狀態(tài);任務(wù)重新得到CPU控制權(quán)時(shí),TCB確保任務(wù)從當(dāng)時(shí)被中斷的那一點(diǎn)絲毫不差地繼續(xù)執(zhí)行。OS_TCB全部駐留在RAM中。任務(wù)控制塊就相當(dāng)于是一個(gè)任務(wù)的身份證,沒(méi)有任務(wù)控制塊的任務(wù)是不能被系統(tǒng)承認(rèn)和管理的。

2.1.2uC/OS-II的任務(wù)—任務(wù)控制塊(TCB)任務(wù)控制塊的結(jié)構(gòu)typedefstructos_tcb{OS_STK*OSTCBStkPtr;//指向當(dāng)前任務(wù)堆棧棧頂?shù)闹羔?。每個(gè)任務(wù)的堆棧容量可以是任意的。#ifOS_TASK_CREATE_EXT_ENvoid*OSTCBExtPtr;//指向任務(wù)控制塊擴(kuò)展的指針,擴(kuò)展功能:任務(wù)執(zhí)行時(shí)間、任務(wù)切換次數(shù)、任務(wù)堆棧使用情況等。OS_STK*OSTCBStkBottom;//指向當(dāng)前任務(wù)堆棧棧底的指針。INT32UOSTCBStkSize;//任務(wù)堆棧的長(zhǎng)度INT16UOSTCBOpt;//創(chuàng)建任務(wù)時(shí)的選擇項(xiàng)INT16UOSTCBId;//用于存儲(chǔ)任務(wù)的識(shí)別碼。保留。#endifstructos_tcb*OSTCBNext;//指向后一個(gè)任務(wù)控制塊的指針structos_tcb*OSTCBPrev;//指向前一個(gè)任務(wù)控制塊的指針#if(OS_Q_EN&&(OS_MAX_QS>=2))||OS_MBOX_EN||OS_SEM_ENOS_EVENT*OSTCBEventPtr;//指向事件控制塊的指針#endif#if(OS_Q_EN&&(OS_MAX_QS>=2))||OS_MBOX_ENvoid*OSTCBMsg;//指向傳遞給任務(wù)消息的指針#endifINT16UOSTCBDly;//任務(wù)等待的時(shí)限INT8UOSTCBStat;//任務(wù)的當(dāng)前狀態(tài)標(biāo)志

INT8UOSTCBPrio;//任務(wù)的優(yōu)先級(jí)別INT8UOSTCBX;//用于快速訪問(wèn)就緒表的數(shù)據(jù)INT8UOSTCBY;//用于快速訪問(wèn)就緒表的數(shù)據(jù)INT8UOSTCBBitX;//用于快速訪問(wèn)就緒表的數(shù)據(jù)INT8UOSTCBBitY;//用于快速訪問(wèn)就緒表的數(shù)據(jù)#ifOS_TASK_DEL_EN

BOOLEANOSTCBDelReq;//請(qǐng)求刪除任務(wù)時(shí)用到的標(biāo)志

#endif}OS_TCB;任務(wù)控制塊結(jié)構(gòu)的主要成員typedefstructos_tcb{OS_STK*OSTCBStkPtr;//指向任務(wù)堆棧棧頂?shù)闹羔?/p>

……

structos_tcb*OSTCBNext;//指向后一個(gè)任務(wù)控制塊的指針

structos_tcb*OSTCBPrev;//指向前一個(gè)任務(wù)控制塊的指針

……INT16U OSTCBDly; //任務(wù)等待的時(shí)限(節(jié)拍數(shù))

INT8U OSTCBStat; //任務(wù)的當(dāng)前狀態(tài)標(biāo)志

INT8U OSTCBPrio; //任務(wù)的優(yōu)先級(jí)別

……}

OS_TCB;任務(wù)控制塊的初始化當(dāng)用戶程序調(diào)用函數(shù)OSTaskCreate()創(chuàng)建一個(gè)任務(wù)時(shí),這個(gè)函數(shù)會(huì)調(diào)用系統(tǒng)函數(shù)OSTCBInit()來(lái)為任務(wù)控制塊進(jìn)行初始化。這個(gè)函數(shù)首先為被創(chuàng)建任務(wù)從空任務(wù)控制塊鏈表獲取一個(gè)任務(wù)控制塊,然后利用任務(wù)的屬性對(duì)任務(wù)控制塊各個(gè)成員進(jìn)行賦值,最后再把這個(gè)任務(wù)控制塊鏈入到任務(wù)控制塊鏈表的頭部。初始化任務(wù)控制塊函數(shù)OSTCBInit()的原型如下:INT8UOSTCBInit(){ INT8U Prio, //任務(wù)的優(yōu)先級(jí)別,保存在OSTCBPrio中

OS_STK *ptos, //任務(wù)堆棧棧頂指針,保存在OSTCBStkPtr中

OS_STK*pbos, //任務(wù)堆棧棧底指針,保存在OSTCBStkBottom中

INT16U id, //任務(wù)的標(biāo)示符,保存在OSTCBId中

INT16U stk_size, //任務(wù)堆棧的長(zhǎng)度,保存在OSTCBStkSize中

void *pext, //任務(wù)控制塊的擴(kuò)展指針,保存在OSTCBExtPtr中

INT16U opt //任務(wù)的控制塊的選擇項(xiàng),保存在OSTCBOpt中};所謂堆棧,就是在存儲(chǔ)器中按數(shù)據(jù)“后進(jìn)先出(LIFO)”的原則組織的連續(xù)存儲(chǔ)空間。為了滿足任務(wù)切換和響應(yīng)中斷時(shí)保存CPU寄存器中的內(nèi)容及存儲(chǔ)任務(wù)私有數(shù)據(jù)的需要,每個(gè)任務(wù)都應(yīng)該配有自己的堆棧。任務(wù)堆棧是任務(wù)的重要組成部分。2.1.3uC/OS-II的任務(wù)—任務(wù)堆棧任務(wù)堆棧的創(chuàng)建為方便定義任務(wù)堆棧,在文件OS_CPU.H中專(zhuān)門(mén)定義了一個(gè)數(shù)據(jù)類(lèi)型OS_STK:TypedefunsignedintOS_STK;

//該類(lèi)型長(zhǎng)度為16位這樣,在應(yīng)用程序中定義任務(wù)堆棧的棧區(qū)就非常簡(jiǎn)單,即定義一個(gè)OS_STK類(lèi)型的一個(gè)數(shù)組即可。例如:#defineTASK_STK_SIZE512//定義堆棧長(zhǎng)度(1024字節(jié))OS_STKTaskStk[TASK_STK_SIZE];//定義一個(gè)數(shù)組來(lái)作為任務(wù)堆棧

創(chuàng)建任務(wù)函數(shù)OSTaskCreate()原型如下:

INT8UOSTaskCreate( void(*task)(void*pd), //指向任務(wù)的指針

void*pdata, //傳遞給任務(wù)的參數(shù)

OS_STK*ptos, //任務(wù)堆棧棧頂?shù)闹羔?/p>

INT8Uprio); //指定任務(wù)優(yōu)先級(jí)別的參數(shù)

當(dāng)調(diào)用函數(shù)OSTaskCreate()來(lái)創(chuàng)建一個(gè)任務(wù)時(shí),把數(shù)組的指針傳遞給函數(shù)OSTaskCreate()中的堆棧棧頂參數(shù)ptos,就可以把該數(shù)組與任務(wù)關(guān)聯(lián)起來(lái)而成為該任務(wù)的任務(wù)堆棧。任務(wù)堆棧的創(chuàng)建堆棧的增長(zhǎng)方向是隨系統(tǒng)所使用的處理器不同而不同。因此在使用函數(shù)OSTaskCreate()創(chuàng)建任務(wù)時(shí),一定要注意所使用的處理器對(duì)堆棧增長(zhǎng)方向的支持是向上的還是向下的。低地址高地址堆棧增長(zhǎng)的方向向下堆棧增長(zhǎng)的方向向上圖3-7堆棧的不同增長(zhǎng)方向上一練習(xí)時(shí)假設(shè)使用了支持堆棧向下增長(zhǎng)方式的處理器設(shè)置參數(shù)ptos。如果使用的處理器支持堆棧的增長(zhǎng)方向向上,則應(yīng)該為: OSTaskCreate(MyTask,&ttt,&MyTaskStk[0],20);為了提高應(yīng)用程序的移植性,在編寫(xiě)代碼時(shí)可兼顧兩種情況,利用OS_CFG.H文件中的常數(shù)OS_STK_GROWTH作為選擇開(kāi)關(guān),使用戶可通過(guò)定義該常數(shù)的值來(lái)選擇相應(yīng)代碼段,以適應(yīng)不同的堆棧增長(zhǎng)方向的需要。試改寫(xiě)上一練習(xí)代碼。任務(wù)堆棧的初始化

uC/OS-II在創(chuàng)建任務(wù)函數(shù)OSTaskCreat()中通過(guò)調(diào)用任務(wù)堆棧初始化函數(shù)OSTaskStkInit()來(lái)完成任務(wù)堆棧初始化工作的,其原型如下:

OS_STK*OSTaskStkInit(

void(*task)(void*pd),

void*pdata,

OS_STK*ptos,

INIT16Uopt

);

由于各處理器的寄存器及對(duì)堆棧的操作方式不同,因此該函數(shù)需要用戶在進(jìn)行uC/OS-II的移植時(shí),按所使用的處理器由用戶來(lái)編寫(xiě)。當(dāng)CPU啟動(dòng)運(yùn)行一個(gè)任務(wù)時(shí),CPU的各寄存器總是需要預(yù)置一些初始數(shù)據(jù),例如指向任務(wù)的指針、任務(wù)堆棧指針、程序狀態(tài)字等。#defineOS_TASK_OPT_STK_CHK0x0001/*Enablestackcheckingforthetask*/#defineOS_TASK_OPT_STK_CLR0x0002/*Clearthestackwhenthetaskiscreate*/#defineOS_TASK_OPT_SAVE_FP0x0004/*Savethecontentsofanyfloating-pointregisters*/最方便的方法就是讓CPU從這個(gè)任務(wù)的任務(wù)堆棧里獲得這些數(shù)據(jù)!任務(wù)堆棧voidmytask(){…..

for(;;){…..}}任務(wù)代碼任務(wù)控制塊指向任務(wù)堆棧的指針…..指向前一個(gè)任務(wù)控制塊的指針指向后一個(gè)任務(wù)控制塊的指針……..任務(wù)的優(yōu)先級(jí)別……任務(wù)2.2uC/OS-II的任務(wù)--存儲(chǔ)結(jié)構(gòu)指向任務(wù)代碼任務(wù)控制塊任務(wù)代碼任務(wù)堆棧任務(wù)1……任務(wù)控制塊鏈表任務(wù)控制塊任務(wù)代碼任務(wù)堆棧任務(wù)2任務(wù)控制塊任務(wù)代碼任務(wù)堆棧任務(wù)n2.2uC/OS-II的任務(wù)--存儲(chǔ)結(jié)構(gòu)uC/OS-II的任務(wù)有5種狀態(tài)睡眠態(tài)(DORMANT):任務(wù)駐留在程序空間,還沒(méi)有交給uCOS管理,即還沒(méi)有配備任務(wù)控制塊,還沒(méi)有被創(chuàng)建。就緒態(tài)(READY):

任務(wù)一旦建立,就進(jìn)入就緒態(tài)準(zhǔn)備運(yùn)行,“萬(wàn)事具備,只欠CPU”。運(yùn)行態(tài)(RUNNING):正在使用CPU的狀態(tài)稱運(yùn)行態(tài)。等待態(tài)(WAITING):等待某事件發(fā)生的狀態(tài).中斷服務(wù)態(tài)(ISR):正在運(yùn)行的任務(wù)被中斷時(shí)就進(jìn)入了中斷服務(wù)態(tài)(ISR)。2.3uC/OS-II的任務(wù)—工作狀態(tài)正在運(yùn)行的任務(wù),需要等待一段時(shí)間或需要等待一個(gè)事件發(fā)生再運(yùn)行時(shí),該任務(wù)就會(huì)把CPU的使用權(quán)讓給別的任務(wù)而使任務(wù)進(jìn)入等待狀態(tài)。任務(wù)在沒(méi)有被配備任務(wù)控制塊或被剝奪了任務(wù)控制塊時(shí)的狀態(tài)叫做任務(wù)的睡眠狀態(tài)

系統(tǒng)為任務(wù)配備了任務(wù)控制塊且在任務(wù)就緒表中進(jìn)行了就緒登記,這時(shí)任務(wù)的狀態(tài)叫做就緒狀態(tài)。

處于就緒狀態(tài)的任務(wù)如果經(jīng)調(diào)度器判斷獲得了CPU的使用權(quán),則任務(wù)就進(jìn)入運(yùn)行狀態(tài)

一個(gè)正在運(yùn)行的任務(wù)一旦響應(yīng)中斷申請(qǐng)就會(huì)中止運(yùn)行而去執(zhí)行中斷服務(wù)程序,這時(shí)任務(wù)的狀態(tài)叫做中斷服務(wù)狀態(tài)

COSII(V2.91版)

支持255個(gè)任務(wù),每個(gè)任務(wù)有一個(gè)特定的優(yōu)先級(jí)。任務(wù)的優(yōu)先級(jí)別用數(shù)字表示,0表示的任務(wù)的優(yōu)先級(jí)最高,數(shù)字越大表示的優(yōu)先級(jí)越低。通過(guò)常數(shù)OS_LOWEST_PRIO(在OS_CFG.H中)定義系統(tǒng)的最低優(yōu)先級(jí)別,同時(shí)限定系統(tǒng)能容納的最多任務(wù)數(shù)量。OS_LOWEST_PRIO給空閑任務(wù),OS_LOWEST_PRIO-1給統(tǒng)計(jì)任務(wù)。2.4uC/OS-II的任務(wù)—優(yōu)先級(jí)

多任務(wù)操作系統(tǒng)的核心:任務(wù)調(diào)度。調(diào)度定義:就是通過(guò)一個(gè)算法在多個(gè)任務(wù)中確定那個(gè)任務(wù)來(lái)運(yùn)行。做這項(xiàng)工作的就是調(diào)度器。任務(wù)調(diào)度的思想:總是讓優(yōu)先級(jí)最高的就緒任務(wù)處于運(yùn)行狀態(tài)。

uC/OS-I進(jìn)行任務(wù)調(diào)度的依據(jù):任務(wù)就續(xù)表。為了能使系統(tǒng)清楚地知道系統(tǒng)中哪些任務(wù)已經(jīng)就緒,那些還沒(méi)有就緒,UC/OS-II在RAM中設(shè)立了一個(gè)記錄表,系統(tǒng)中的每個(gè)任務(wù)都在這個(gè)表占據(jù)一個(gè)位置,并用這個(gè)位置的狀態(tài)(1或者0)來(lái)表示任務(wù)是否處于就緒狀態(tài)。這個(gè)表就叫做任務(wù)就緒表。2.5uC/OS-II的任務(wù)—任務(wù)就緒表及調(diào)度每個(gè)就緒的任務(wù)都放入就緒表中,就緒表有兩個(gè)變量:OSRdyGrp、OSRdyTbl[]OSRdyGrp1207654300XXXYYY任務(wù)優(yōu)先級(jí)2017654310891514131211181617232221201926242531302928273432333938373635424041474645444350484955545352515856576362616059[0][1][2][3][4][5][6][7]XY優(yōu)先級(jí)最低任務(wù)優(yōu)先級(jí)最高任務(wù)任務(wù)優(yōu)先級(jí)號(hào)(idletask)任務(wù)就緒表的結(jié)構(gòu)圖2-10就緒表的結(jié)構(gòu)由于每個(gè)任務(wù)的就緒狀態(tài)只占一位,因此OSRdyTbl[]數(shù)組的一個(gè)元素可表達(dá)8個(gè)任務(wù)的就緒狀態(tài)。即每一個(gè)數(shù)組元素描述了8個(gè)任務(wù)的就緒狀態(tài),于是這8個(gè)任務(wù)就可以看成一個(gè)任務(wù)組。數(shù)據(jù)類(lèi)型為INT8U的變量OSRdyGrp,該變量的每一個(gè)位都對(duì)應(yīng)OSRdyTbl[]的一個(gè)任務(wù)組(即數(shù)組的一個(gè)元素)。任務(wù)就緒表的結(jié)構(gòu)如何根據(jù)任務(wù)的優(yōu)先級(jí)別查找任務(wù)在就緒表的位置呢?例:已知某一個(gè)已經(jīng)就緒的任務(wù)優(yōu)先級(jí)別為prio=30,試判斷應(yīng)該在就緒表的哪一位置上置1。分析:由于優(yōu)先級(jí)別是一個(gè)單字節(jié)的數(shù)字,而且最大值不會(huì)超過(guò)63,即二進(jìn)制00111111,因此,可以把優(yōu)先級(jí)別看成是一個(gè)6位的二進(jìn)制數(shù),這樣就可以用高3位(D5、D4、D3)來(lái)指明變量OSRdyGrp的具體數(shù)據(jù)位,并用來(lái)確定就緒表數(shù)組元素的下標(biāo);用低3位(D2、D1、D0)來(lái)指明該數(shù)組元素的具體數(shù)據(jù)位。答:30的二進(jìn)制形式為00011110,其低6位為011110,于是可知應(yīng)該在OSRdyTbl[3]的D6位上置1,同時(shí)要把變量OSRdyGrp的D3位置1。對(duì)任務(wù)就緒表的操作在程序中,可用類(lèi)似于下面的代碼把優(yōu)先級(jí)為prio的任務(wù)置為就緒態(tài)。OSRdyGrp|=OSMapTbl[prio>>3];OSRdyTbl[prio>>3]|=OSMapTbl[prio&0x07];其中,OSMapTbl[]是uC/OS-II為加快運(yùn)算速度定義的一個(gè)數(shù)組,各元素為: OSMapTbl[0]=00000001B OSMapTbl[1]=00000010B OSMapTbl[2]=00000100B OSMapTbl[3]=00001000B OSMapTbl[4]=00010000B OSMapTbl[5]=00100000B OSMapTbl[6]=01000000B OSMapTbl[7]=10000000B如果要使一個(gè)優(yōu)先級(jí)為prio的任務(wù)脫離就緒態(tài),則可使用如下代碼:If((OSRdyTbl[prio>>3]&=OSMapTbl[prio&0x07])==0)OSRdyGrp&=OSMapTbl[prio>>3];將任務(wù)就緒表OSRdyTbl[prio>>3]相應(yīng)元素的相應(yīng)位清零,而且當(dāng)OSRdyTbl[prio>>3]中的所有位都為零時(shí),即全組任務(wù)中沒(méi)有一個(gè)進(jìn)入就緒態(tài)時(shí),OSRdyGrp的相應(yīng)位才為零。對(duì)任務(wù)就緒表的操作(續(xù))例:欲使優(yōu)先級(jí)為12的任務(wù)進(jìn)入就緒態(tài),設(shè)置就緒表。答:優(yōu)先級(jí)為12,即00001100B。OSRdyGrp|=OSMapTbl[prio>>3]=OSMapTbl[1]=00000010;OSRdyTbl[1]|=OSMapTbl[prio&0x07]=OSMapTbl[4]=00010000;例:欲使優(yōu)先級(jí)為12的任務(wù)脫離就緒態(tài),設(shè)置就緒表。答:優(yōu)先級(jí)為12,即00001100B。OSMapTbl[prio&0x07]=OSMapTbl[4]=11101111OSMapTbl[prio>>3]=OSMapTbl[1]=11111101由于OSRdyTbl[prio>>3]&=OSMapTbl[prio&0x07]=0

則OSRdyGrp=OSRdyGrp&OSMapTbl[prio>>3]=0從任務(wù)就緒表中獲取優(yōu)先級(jí)別最高的就緒任務(wù)可用如下代碼:采用查表法確定高優(yōu)先級(jí)任務(wù)Y=OSUnMapTbl[OSRdyGrp]; //獲得優(yōu)先級(jí)別的D5、D4、D3位X=OSUnMapTbl[OSRdyTbl[Y]];//獲得優(yōu)先級(jí)別的D2、D1、D0位Prio=(Y<<3)+X; //獲得就緒任務(wù)的優(yōu)先級(jí)別其中,OSUnMapTbl[]同樣是uC/OS-II為加快運(yùn)算速度定義的一個(gè)數(shù)組,共有256個(gè)元素: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};舉例:如OSRdyGrp的值為01101000B,即104,則查得OSUnMapTbl[OSRdyGrp]的值是3。如OSRdyTbl[3]的值是11100100B,即228,則查OSUnMapTbl[OSRdyTbl[3]]的值是2。則進(jìn)入就緒態(tài)的最高任務(wù)優(yōu)先級(jí)。

Prio=3*8+2=26

UC/OS-II經(jīng)常使用類(lèi)似于就緒表的形式來(lái)記錄任務(wù)的某種狀態(tài),因此一定要熟悉這種表的結(jié)構(gòu)以及對(duì)這種表的基本操作。任務(wù)切換:在多任務(wù)系統(tǒng)中,令CPU中止當(dāng)前正在運(yùn)行的任務(wù)而去運(yùn)行另一個(gè)任務(wù)的工作。任務(wù)調(diào)度:按某種規(guī)則進(jìn)行任務(wù)切換的工作。任務(wù)調(diào)度由任務(wù)調(diào)度器完成,調(diào)度器主要工作:

1.在任務(wù)就緒表中查找具有最高優(yōu)先級(jí)別的就緒任務(wù)。

2.實(shí)現(xiàn)任務(wù)切換。uC/OS-II有兩種調(diào)度器:

任務(wù)級(jí)調(diào)度器(由OSSched()實(shí)現(xiàn))、中斷級(jí)調(diào)度器(由OSIntExt()實(shí)現(xiàn))。任務(wù)切換的兩個(gè)步驟:

1.獲得待運(yùn)行任務(wù)的TCB指針。

2.進(jìn)行斷點(diǎn)數(shù)據(jù)的切換。任務(wù)的調(diào)度任務(wù)切換過(guò)程獲得待運(yùn)行任務(wù)的任務(wù)控制塊恢復(fù)待運(yùn)行任務(wù)的運(yùn)行環(huán)境處理器的PC=任務(wù)堆棧中的斷點(diǎn)地址處理器的SP=任務(wù)塊中保存的SP如何獲得待運(yùn)行任務(wù)的任務(wù)控制塊?根據(jù)就緒表獲得待運(yùn)行任務(wù)的任務(wù)控制塊指針其實(shí),調(diào)度器在進(jìn)行調(diào)度時(shí),在這個(gè)位置還要進(jìn)行一下判斷:究竟是待運(yùn)行任務(wù)是否為當(dāng)前任務(wù),如果是,則不切換;如果不是才切換,而且還要保存被中止任務(wù)的運(yùn)行環(huán)境。任務(wù)代碼任務(wù)堆棧內(nèi)存處理器PCSP處理器通過(guò)兩個(gè)指針寄存器(PC和SP)來(lái)與任務(wù)代碼和任務(wù)堆棧建立聯(lián)系并運(yùn)行它寄存器組程序運(yùn)行環(huán)境運(yùn)行環(huán)境包括了兩部分:處理器中的運(yùn)行環(huán)境和內(nèi)存中的運(yùn)行環(huán)境任務(wù)運(yùn)行時(shí)與處理器之間的關(guān)系任務(wù)代碼任務(wù)堆棧內(nèi)存處理器PCSP多任務(wù)時(shí)的問(wèn)題任務(wù)代碼任務(wù)堆棧內(nèi)存任務(wù)代碼任務(wù)堆棧內(nèi)存?當(dāng)有多個(gè)任務(wù)時(shí),處理器中的運(yùn)行環(huán)境應(yīng)該怎么辦?寄存器組程序運(yùn)行環(huán)境程序

虛擬處理器PCSP

虛擬處理器PCSP

虛擬處理器PCSP

虛擬處理器PCSP調(diào)度器多任務(wù)時(shí)任務(wù)與處理器之間關(guān)系的處理程序處理器PCSP在內(nèi)存中為每個(gè)任務(wù)創(chuàng)建一個(gè)虛擬的處理器(處理器部分的運(yùn)行環(huán)境由操作系統(tǒng)的調(diào)度器按某種規(guī)則來(lái)進(jìn)行這兩個(gè)復(fù)制工作復(fù)制當(dāng)需要運(yùn)行某個(gè)任務(wù)時(shí)就把該任務(wù)的虛擬處理器復(fù)制到實(shí)際處理器中復(fù)制當(dāng)需要中止當(dāng)前任務(wù)時(shí),則把任務(wù)對(duì)應(yīng)的虛擬處理器復(fù)制到內(nèi)存復(fù)制再把另一個(gè)需要運(yùn)行的任務(wù)的虛擬處理器復(fù)制到實(shí)際處理器中寄存器組寄存器組也就是說(shuō),任務(wù)的切換是任務(wù)運(yùn)行環(huán)境的切換任務(wù)切換宏OS_TASK_SW()

任務(wù)切換就是中止正在運(yùn)行的任務(wù)(當(dāng)前任務(wù)),轉(zhuǎn)而去運(yùn)行另外一個(gè)任務(wù)的操作,當(dāng)然這個(gè)任務(wù)應(yīng)該是就緒任務(wù)中優(yōu)先級(jí)別最高的那個(gè)任務(wù)。需要由宏OS_TASK_SW()

來(lái)引發(fā)一次中斷或者一次調(diào)用來(lái)使OSCtxSw()執(zhí)行任務(wù)切換工作,任務(wù)切換OSCtxSw()是一個(gè)中斷服務(wù)程序。任務(wù)的調(diào)度(續(xù))1.獲得待運(yùn)行任務(wù)的TCB指針voidOSSched(void){INT8Uy;OS_ENTER_CRITICAL();if((OSLockNesting|OSIntNesting)==0)//未被上鎖且不是中斷服務(wù)程序調(diào)用

{

y=OSUnMapTbl[OSRdyGrp]; OSPrioHighRdy=(INT8U)((y<<3)+OSUnMapTbl[OSRdyTbl[y]]);//得到最高優(yōu)先級(jí)任務(wù)

if(OSPrioHighRdy!=OSPrioCur)//不是當(dāng)前運(yùn)行任務(wù)

{

OSTCBHighRdy=OSTCBPrioTbl[OSPrioHighRdy];//得到待運(yùn)行任務(wù)控制塊指針OSCtxSwCtr++;//統(tǒng)計(jì)任務(wù)切換次數(shù)的計(jì)數(shù)器加1OS_TASK_SW();//實(shí)施任務(wù)切換

}}OS_EXIT_CRITICAL();}由于操作系統(tǒng)是通過(guò)任務(wù)的任務(wù)控制塊TCB來(lái)管理任務(wù)的,因此調(diào)度器真正實(shí)施任務(wù)切換之前的主要工作是要獲得待運(yùn)行任務(wù)的任務(wù)控制塊指針和當(dāng)前任務(wù)的任務(wù)控制塊指針。任務(wù)的調(diào)度(續(xù))2.任務(wù)切換宏OS_TASK_SW()SPR1R2……RnPCPSWR1R2……RnPCPSWR1R2……RnPCPSWCPU的各寄存器被中止任務(wù)TCB待運(yùn)行任務(wù)TCBOSTCBStkPtrOSTCBStkPtr被中止任務(wù)堆棧待運(yùn)行任務(wù)堆棧圖2-11調(diào)度器進(jìn)行任務(wù)切換時(shí)的動(dòng)作斷點(diǎn):任務(wù)被中止運(yùn)行時(shí)的位置。斷點(diǎn)數(shù)據(jù):當(dāng)時(shí)存放在CPU的各寄存器中的數(shù)據(jù)。“無(wú)縫”接續(xù):當(dāng)任務(wù)恢復(fù)運(yùn)行時(shí),必須在斷點(diǎn)處以斷點(diǎn)數(shù)據(jù)作為初始數(shù)據(jù)接著運(yùn)行。正確地恢復(fù)斷點(diǎn)數(shù)據(jù)的關(guān)鍵:CPU的堆棧指針SP是否有正確的指向。在系統(tǒng)中存在多個(gè)任務(wù)時(shí),如果在恢復(fù)斷點(diǎn)數(shù)據(jù)使用另一個(gè)任務(wù)的任務(wù)堆棧指針(存放在TCB的OSTCBStkPtr中)來(lái)改變CPU的堆棧指針SP,那么CPU運(yùn)行的就不是剛才被中止運(yùn)行的任務(wù),而使另一個(gè)任務(wù)了,也就是實(shí)現(xiàn)任務(wù)切換了。為了了解調(diào)度器是如何進(jìn)行任務(wù)切換的,探討一下一個(gè)被中止運(yùn)行的任務(wù),將來(lái)又要“無(wú)縫”地恢復(fù)運(yùn)行應(yīng)該滿足的條件2.7任務(wù)的操作—?jiǎng)?chuàng)建uC/OS-II是通過(guò)任務(wù)控制塊來(lái)管理任務(wù)的。

uC/OS-II有兩個(gè)用來(lái)創(chuàng)建任務(wù)的函數(shù):TaskCreate()、OSTaskCreateExt()OSTaskCreate()向下兼容,OSTaskCreateExt()是前一函數(shù)的擴(kuò)展,提供了一些附加功能。任務(wù)可以在多任務(wù)調(diào)度開(kāi)始前建立,也可以在其他任務(wù)執(zhí)行過(guò)程中建立。任務(wù)不能由中斷服務(wù)程序建立。創(chuàng)建任務(wù)的一般方法

可在調(diào)用函數(shù)OSStart()啟動(dòng)任務(wù)調(diào)度之前來(lái)創(chuàng)建。在任務(wù)中來(lái)創(chuàng)建。

uC/OS-II的規(guī)定:在OSStart()啟動(dòng)任務(wù)調(diào)度之前必須創(chuàng)建至少一個(gè)任務(wù)。這樣,在OSStart()之前先創(chuàng)建一個(gè)任務(wù),并賦予它最高的優(yōu)先級(jí),從而使它成為起始任務(wù),然后在這個(gè)起始任務(wù)中,在創(chuàng)建其它各任務(wù)。如果要使用系統(tǒng)提供的統(tǒng)計(jì)任務(wù),則統(tǒng)計(jì)任務(wù)的初始化函數(shù)必須在這個(gè)起始任務(wù)中來(lái)調(diào)用。

uC/OS-II不允許在中斷服務(wù)程序中創(chuàng)建任務(wù)!創(chuàng)建任務(wù)的一般方法/*****************************主函數(shù)**********************************/voidmain(void){

…… OSInit(); //對(duì)uC/OS-II初始化

…… OSTaskCreate(TaskStart,……); //創(chuàng)建起始任務(wù)

OSStart(); //開(kāi)始多任務(wù)調(diào)度}/*****************************起始任務(wù)*********************************/voidTaskStart(void*pdata){

…… //在這個(gè)位置安裝并啟動(dòng)uC/OS-II時(shí)鐘

OSStatInit(); //初始化統(tǒng)計(jì)任務(wù)

…… //在這個(gè)位置創(chuàng)建其它任務(wù)

For(;;) {

起始任務(wù)的代碼

}}

所謂掛起一個(gè)任務(wù),就是停止這個(gè)任務(wù)的運(yùn)行。在uC/OS-II中,用戶任務(wù)可通過(guò)調(diào)用系統(tǒng)提供的函數(shù)OSTaskSuspend()來(lái)掛起自身或者除空閑任務(wù)之外的其他任務(wù)。用函數(shù)OSTaskSuspend()掛起的任務(wù),只能在其它任務(wù)中通過(guò)調(diào)用恢復(fù)函數(shù)OSTaskResume()使其恢復(fù)為就緒狀態(tài)。等待狀態(tài)就緒狀態(tài)運(yùn)行狀態(tài)OS_TASK_SW()OSTaskResume()OSTaskSuspend()

任務(wù)的CPU使用權(quán)被剝奪圖任務(wù)的掛起和恢復(fù)2.7任務(wù)的操作—掛起與恢復(fù)

刪除任務(wù),就是把該任務(wù)處于休眠狀態(tài)。并不是說(shuō)任務(wù)的代碼真的被刪除了,只是任務(wù)的代碼不再被操作系統(tǒng)調(diào)用。通過(guò)調(diào)用OSTaskDel()就可以完成刪除任務(wù)自身或除了空閑任務(wù)之外的其他任務(wù)。

函數(shù)OSTaskDel()的原型如下:

#ifOS_TASK_DEL_ENINT8UOSTaskDel( INT8Uprio //要?jiǎng)h除任務(wù)的優(yōu)先級(jí)

);

如果任務(wù)刪除自己,則應(yīng)在調(diào)用函數(shù)時(shí)令函數(shù)的參數(shù)prio為OS_PRIO_SELF。

刪除任務(wù)具體做法是,把被刪除任務(wù)的任務(wù)控制塊從任務(wù)控制塊鏈表中刪除,并歸還給空任務(wù)控制塊鏈表,然后在任務(wù)就緒表中把該任務(wù)的就緒狀態(tài)位置0,于是該任務(wù)就不能再被調(diào)度器調(diào)用了。2.7任務(wù)的操作—?jiǎng)h除請(qǐng)求刪除任務(wù)函數(shù)OSTaskDelReq()的原型如下:

INT8UOSTaskDelReq( INT8Uprio //要?jiǎng)h除任務(wù)的優(yōu)先級(jí)

);

如果任務(wù)請(qǐng)求刪除自己,則應(yīng)在調(diào)用函數(shù)時(shí)令函數(shù)的參數(shù)prio為OS_PRIO_SELF。

進(jìn)入Prio是空閑任務(wù)?

返回OS_TASK_NOT_EXIST

返回OS_TASK_IDLE_PRIO返回被刪除任務(wù)TCB的成員OSTCBDelReq的值NOYESYESYES

返回OS_NO_ERRNOPrio是合法優(yōu)先級(jí)?

返回OS_PRIO_INVALIDNOPrio=OS_PRIO_SELF?Prio任務(wù)的TCB不存在?NOYES圖2-15函數(shù)OSTaskDelReq()流程圖提出刪除請(qǐng)求任務(wù)的執(zhí)行路徑被刪除任務(wù)的執(zhí)行路徑有時(shí)任務(wù)會(huì)占用一些動(dòng)態(tài)分配的資源,這時(shí)如果有其他任務(wù)把這個(gè)任務(wù)刪除了,那么被刪除任務(wù)所占用的一些資源就會(huì)因?yàn)闆](méi)有被釋放而丟失,這是任何系統(tǒng)都無(wú)法接受的。具體辦法是:提出刪除任務(wù)請(qǐng)求的任務(wù)只負(fù)責(zé)刪除任務(wù)請(qǐng)求,而刪除工作則由被刪除任務(wù)自己來(lái)完成。這樣,被刪除任務(wù)就可以根據(jù)自身的具體情況來(lái)決定何時(shí)刪除自身,同時(shí)也有機(jī)會(huì)在刪除自身之前把占用的資源釋放掉。2.7任務(wù)的操作—請(qǐng)求刪除任務(wù)在用戶建立任務(wù)的時(shí)候會(huì)分配給任務(wù)一個(gè)優(yōu)先級(jí)。在程序運(yùn)行期間,用戶可以通過(guò)調(diào)用OSTaskChangePrio()來(lái)改變?nèi)蝿?wù)的優(yōu)先級(jí)。換句話說(shuō),就是μC/OS-Ⅱ允許用戶動(dòng)態(tài)的改變?nèi)蝿?wù)的優(yōu)先級(jí)。函數(shù)OSTaskChangePrio()的原型如下:

INT8UOSTaskChangePrio( INT8Uoldprio, //任務(wù)現(xiàn)在的優(yōu)先級(jí)

INT8Unewprio//要修改的優(yōu)先級(jí)

);

2.7任務(wù)的操作—改變?nèi)蝿?wù)優(yōu)先級(jí)INT8UOSTaskQuery( INT8Uprio, //待查詢?nèi)蝿?wù)的優(yōu)先級(jí)

OS_TCB*pdata //存儲(chǔ)任務(wù)信息的結(jié)構(gòu)

);函數(shù)OSTaskQuery()的原型如下:

有時(shí),在應(yīng)用程序運(yùn)行中需要了解一個(gè)任務(wù)的指針、堆棧等信息,這時(shí)可通過(guò)調(diào)用函數(shù)OSTaskQuery()來(lái)獲取選定的任務(wù)的信息。若調(diào)用函數(shù)OSTaskQuery()查詢成功,則返回OS_NO_ERR,并把查詢得到的任務(wù)信息存放在結(jié)構(gòu)OS_TCB類(lèi)型的變量中。2.7任務(wù)的操作—查詢?nèi)蝿?wù)信息系統(tǒng)首先調(diào)用初始化函數(shù)OSIint()。OSIint()初始化μC/OS-Ⅱ所有的變量和數(shù)據(jù)結(jié)構(gòu)。OSInit()建立空閑任務(wù)idletask,這個(gè)任務(wù)總是處于就緒態(tài)的。空閑任務(wù)OSTaskIdle()的優(yōu)先級(jí)總是設(shè)成最低,即OS_LOWEST_PRIO。如果統(tǒng)計(jì)任務(wù)允許OS_TASK_STAT_EN和任務(wù)建立擴(kuò)展允許都設(shè)為1,則OSInit()還得建立統(tǒng)計(jì)任務(wù)OSTaskStat()并且讓其進(jìn)入就緒態(tài)。OSTaskStat的優(yōu)先級(jí)總是設(shè)為OS_LOWEST_PRIO-1。

初始化時(shí)主要是創(chuàng)建包括空任務(wù)控制塊鏈表在內(nèi)的5個(gè)空數(shù)據(jù)緩沖區(qū),及按任務(wù)優(yōu)先級(jí)存放任務(wù)控制塊指針的數(shù)組OSTCBPrioTbl[OS_LOWEST_PRIO+1]。2.8uC/OS-II的初始化uC/OS-II初始化后的數(shù)據(jù)結(jié)構(gòu)000000000000000000000000000000000000000000000000000000001100000000000001圖2-16uC/OS-II初始化后的數(shù)據(jù)結(jié)構(gòu)任務(wù)就緒表

OSRdyGrp任務(wù)就緒表

OSRdyTbl[]●●[OS_LOWEST_PRIO-1][OS_LOWEST_PRIO]OSTCBPrioTbl[][0][1][2]

空任務(wù)控制塊

空任務(wù)控制塊

空任務(wù)控制塊……OSTCBStkBottom……OSTCBStkPtr…………OSTCBStkBottom……OSTCBStkPtr……統(tǒng)計(jì)任務(wù)的控制塊空閑任務(wù)的控制塊OSTCBFreeList

任務(wù)控制塊鏈表OSTCBList

統(tǒng)計(jì)任務(wù)堆棧

空閑任務(wù)堆棧

其余4個(gè)鏈表1425uC/OS-II的任務(wù)3uC/OS-II的移植uC/OS-II同步與通信uC/OS-II概述uC/OS-III簡(jiǎn)介目錄uC/OS-II的移植3.1基于Cortex-M3內(nèi)核的移植3.2基于ARM7內(nèi)核的移植μC/OS-II移植應(yīng)用程序(用戶代碼)μC/OS-II(與處理器無(wú)關(guān)代碼)OS_CORE.cOS_FLAG.c...μC/OS-II配置(與應(yīng)用無(wú)關(guān))OS_CFG.HINCLUDES.H

μC/OS-II移植(與處理器相關(guān)代碼)CPU定時(shí)器硬件軟件——μC/OS-II硬件軟件體系結(jié)構(gòu)用于產(chǎn)生系統(tǒng)時(shí)鐘移植時(shí)需要編寫(xiě)的代碼54User目錄Main.CMain.HIncludes.HOS_Cfg.HμC/OS-II

Source目錄OS_CORE.COS_FLAG.COS_MBOX.COS_MEM.COS_MUTEX.COS_Q.COS_SEM.COS_TASK.COS_TIME.COS_TMR.CuCOS_II.HμC/OS-II

Ports目錄CortexM3

OS_CPU_C.COS_CPU_A.ASMOS_CPU.HBSP(板級(jí)支持包)Startup.STarget.CTarget.H

ARMCortex-M3

目標(biāo)板與處理器無(wú)關(guān)操作系統(tǒng)內(nèi)核代碼與處理器有關(guān)需要移植代碼開(kāi)發(fā)板相關(guān)代碼3.1基于ARMCortex-M3的移植55內(nèi)核文件移植的部分用戶代碼配置代碼主任務(wù)56ARMCortex-M3的寄存器模型在移植之前,先簡(jiǎn)述ARMCortex-M3寄存器模型。ARMCortex-M3總共有20個(gè)寄存器,每個(gè)都是32位寬度。R0-R12通用寄存器,可存儲(chǔ)數(shù)據(jù)也可存放指針R13用于存放堆棧指針。實(shí)際上有兩個(gè)堆棧指針SP_process(進(jìn)程堆棧)和

SP_main(主堆棧),但任何時(shí)候只有一個(gè)是可見(jiàn)的。在本移植中,

SP_process用于任務(wù)代碼(即線程模式),SP_main用于異常代碼(即處理模式)。R14連接寄存器LR。在執(zhí)行分支鏈接指令(BL)或帶交換的分支鏈接指令(BLX)時(shí),存儲(chǔ)來(lái)自PC的返回地址;也用作異常的返回。R15程序計(jì)數(shù)寄存器PC。用于指示當(dāng)前正被執(zhí)行的指令。根據(jù)不同的指令,每執(zhí)行一條,PC增加2或增加4。5758狀態(tài)中斷59控制寄存器603.1.1移植條件移植μC/OS-II到處理器上必須滿足以下條件:(1)處理器的C編譯器能產(chǎn)生可重入代碼μC/OS是多任務(wù)內(nèi)核,函數(shù)可能會(huì)被多個(gè)任務(wù)調(diào)用,代碼的重入性是保證完成多任務(wù)的基礎(chǔ)??芍厝氪a指的是可被多個(gè)體任務(wù)同時(shí)調(diào)用,而不會(huì)破壞數(shù)據(jù)的一段代碼,或者說(shuō)代碼具有在執(zhí)行過(guò)程中打斷后再次被調(diào)用的能力。舉例說(shuō)明:Swap1函數(shù)代碼:Inttemp;voidswap1(int*x,int*y){temp=*x;*x=*y;*y=temp;}舉例說(shuō)明:Swap2函數(shù)代碼:voidswap2(int*x,int*y){inttemp;temp=*x;*x=*y;*y=temp;}可重入不可重入編譯器還得支持,MDK開(kāi)發(fā)環(huán)境,可生成可重入代碼61(2)用C語(yǔ)言可打開(kāi)和關(guān)閉中斷ARM處理器核包含一個(gè)CPSR寄存器,該寄存器包括一個(gè)全局的中斷禁止位,控制它便可打開(kāi)和關(guān)閉中斷。PRIMASK(3)處理器支持中斷并且能產(chǎn)生定時(shí)中斷μC/OS-II通過(guò)處理器產(chǎn)生的定時(shí)器中斷來(lái)實(shí)現(xiàn)多任務(wù)之間的調(diào)度。ARMCortex-M3的處理器都支持中斷并能產(chǎn)生定時(shí)器中斷,專(zhuān)門(mén)有一個(gè)SysTick定時(shí)器來(lái)實(shí)現(xiàn)。(4)處理器支持能夠容納一定量數(shù)據(jù)的硬件堆棧(通常需要幾十KByte字節(jié))

比如AT98C51處理器,內(nèi)部只有128字節(jié)的RAM,要運(yùn)行,需外擴(kuò)RAM。CM3的芯片,內(nèi)部可多達(dá)128KByte的容量,因此可直接使用。(5)處理器有將堆棧指針和其他CPU寄存器讀出和存儲(chǔ)到堆棧(或內(nèi)存)的指令

μC/OS-II進(jìn)行任務(wù)調(diào)度時(shí),會(huì)把當(dāng)前任務(wù)的CPU寄存器存到此任務(wù)的堆棧中,然后,再?gòu)牧硪粋€(gè)任務(wù)的堆棧中恢復(fù)原來(lái)的工作寄存器,繼續(xù)運(yùn)行另一個(gè)任務(wù)。所以,寄存器的入棧和出棧是μC/OS-II多任務(wù)調(diào)度的基礎(chǔ)。運(yùn)行TCP、UDP需要的內(nèi)存會(huì)更大,通常要100K左右62

所謂移植,就是使一個(gè)實(shí)時(shí)操作系統(tǒng)能夠在某個(gè)微處理器平臺(tái)上或微控制器平臺(tái)上運(yùn)行。由μC/OS-II的文件系統(tǒng)可知,在移植過(guò)程中,用戶需要關(guān)注的就是與處理器相關(guān)的代碼。這部分包括一個(gè)頭文件OS_CPU.H、一個(gè)匯編文件OS_CPU_A.ASM和一個(gè)C代碼文件OS_CPU_C.C。OS_CPU.HOS_CPU_C.COS_CPU_A.ASM#define設(shè)置一個(gè)常量的值聲明10個(gè)數(shù)據(jù)類(lèi)型用#define聲明三個(gè)宏用C語(yǔ)言編寫(xiě)六個(gè)簡(jiǎn)單的函數(shù)編寫(xiě)四個(gè)匯編語(yǔ)言函數(shù)移植實(shí)際中,寫(xiě)一個(gè)就行3.1.2移植步驟631、INCLUDES.HINCLUDES.H是一個(gè)頭文件,它在所有.C文件的第一行被包含。#include"includes.h"INCLUDES.H使得用戶項(xiàng)目中的每個(gè).C文件不用分別去考慮它實(shí)際上需要哪些頭文件。使用INCLUDES.H的唯一缺點(diǎn)是它可能會(huì)包含一些實(shí)際不相關(guān)的頭文件。這意味著每個(gè)文件的編譯時(shí)間可能會(huì)增加。但由于它增強(qiáng)了代碼的可移植性,所以我們還是決定使用這一方法。用戶可以通過(guò)編輯INCLUDES.H來(lái)增加自己的頭文件,但是用戶的頭文件必須添加在頭文件列表的最后。2、基本配置和定義OS_CPU.H(1)用#define設(shè)置一個(gè)常量的值#ifdefOS_CPU_GLOBALS#defineOS_CPU_EXT#else#defineOS_CPU_EXTextern#endif64(2)定義與編譯器相關(guān)的數(shù)據(jù)類(lèi)型

為了保證可移植性,程序中沒(méi)有直接使用C語(yǔ)言中的short、int和long等數(shù)據(jù)類(lèi)型的定義,因?yàn)樗鼈兣c處理器類(lèi)型有關(guān),隱含著不可移植性。程序中自己定義了一套數(shù)據(jù)類(lèi)型,如INT16U表示16位無(wú)符號(hào)整型。對(duì)于ARM這樣的32位內(nèi)核,INT16U是unsignedshort型;如果是16位處理器,則是unsingedint型。typedefunsignedcharBOOLEAN;/*Boolean布爾變量*/typedefunsignedcharINT8U;/*無(wú)符號(hào)8位實(shí)體*/typedefsignedcharINT8S;/*有符號(hào)8位實(shí)體*/typedefunsignedshortINT16U;/*無(wú)符號(hào)16位實(shí)體*/typedefsignedshortINT16S;/*有符號(hào)16位實(shí)體*/typedefunsignedintINT32U;/*無(wú)符號(hào)32位實(shí)體*/typedefsignedintINT32S;/*有符號(hào)32位實(shí)體*/typedeffloatFP32/*單精度浮點(diǎn)數(shù)*/typedefdoubleFP64;/*雙精度浮點(diǎn)數(shù)*/typedefunsignedintOS_STK;/*堆棧是32位寬度*/typedefunsignedintOS_CPU_SR;/*申明狀態(tài)寄存器是32位*/μC/OS-II內(nèi)核的代碼需要與處理器位有關(guān)65(3)定義臨界段(允許和禁止中斷宏)

與所有實(shí)時(shí)內(nèi)核一樣,μC/OS-II需要先禁止中斷,再訪問(wèn)代碼的臨界區(qū),并且在訪問(wèn)完畢后,重新允計(jì)中斷。這就是μC/OS-II能夠保護(hù)臨界段代碼免受多任務(wù)或中斷服務(wù)例程ISR的破壞。中斷禁止時(shí)間是商業(yè)實(shí)時(shí)內(nèi)核公司提供的重要指標(biāo)之一,因?yàn)樗鼘⒂绊懙接脩舻南到y(tǒng)對(duì)實(shí)時(shí)事件的響應(yīng)能力。雖然μC/OS-II盡量使中斷禁止時(shí)間達(dá)到最短,但是μC/OS-II的中斷禁止時(shí)間還主要依賴于處理器結(jié)構(gòu)和編譯器產(chǎn)生的代碼的質(zhì)量。通常每個(gè)處理器都會(huì)提供一定的指令來(lái)禁止/允許中斷,因此用戶的C編譯器必須由一定的機(jī)制來(lái)直接從C中執(zhí)行這些操作。OS_ENTER_CRITICAL()OS_EXIT_CRITICAL()μC/OS-II定義了兩個(gè)宏來(lái)禁止和允許中斷:#defineOS_CRITICAL_METHOD3#defineOS_ENTER_CRITICAL(){cpu_sr=OS_CPU_SR_Save();}#defineOS_EXIT_CRITICAL(){OS_CPU_SR_Restore(cpu_sr);}μC/OS-II定義了三種方法關(guān)閉和打開(kāi)中斷(OS_CRITICAL_METHED=1,2,3),通常情況下,我們都是選用的方法3。66OS_CPU_SR_SaveMRSR0,PRIMASKCPSIDIBXLROS_CPU_SR_RestoreMSRPRIMASK,R0BXLR關(guān)中斷開(kāi)中斷(4)定義棧的增長(zhǎng)方向μC/OS-II使用結(jié)構(gòu)常量OS_STK_GROWTH來(lái)指定堆棧的增長(zhǎng)方式:置OS_STK_GROWTH為0,表示堆棧從下往上增長(zhǎng);置OS_STK_GROWTH為1,表示堆棧從上往下增長(zhǎng)。Cortex-M3支持從上往下增長(zhǎng)的方式。因此,我們?cè)谝浦矔r(shí),需將OS_STK_GROWTH=1,如果是51系列單片機(jī),則OS_STK_GROWTH=0。#defineOS_STK_GROWTH1

67(5)定義OS_TASK_SW()宏,任務(wù)級(jí)上下文切換

任務(wù)級(jí)上下文切換(即任務(wù)切換)調(diào)用宏定義OS_TASK_SW()。因?yàn)樯舷挛那袚Q跟處理器有密切關(guān)系,OS_TASK_SW()實(shí)質(zhì)上是調(diào)用匯編函數(shù)OSCtxSW(),它在OS_CPU_A.ASM文件中定義。#defineOS_TASK_SW()OSCtxSw()OSCtxSwPUSH{R4,R5}LDRR4,=NVIC_INT_CTRL;觸發(fā)軟件中斷

LDRR5,=NVIC_PENDSVSETSTRR5,[R4]POP{R4,R5}BXLR原型如下:打開(kāi)MDK查看原始代碼NVIC_INT_CTRLEQU0xE000ED04NVIC_PENDSVSETEQU0x10000000當(dāng)執(zhí)行完這段代后,自運(yùn)的產(chǎn)生PendSV中斷,也即14號(hào)異常,自動(dòng)跳到14號(hào)異常服務(wù)程序執(zhí)行。在本移植中則會(huì)直接去執(zhí)行:OSPendSV部分內(nèi)容68中斷控制及狀態(tài)寄存器ICSR0xE000_ED04設(shè)置1將掛起中斷693、移植匯編語(yǔ)言編寫(xiě)的4個(gè)與處理器相關(guān)的函數(shù)OS_CPU_A.ASM(1)OSStartHighRdy():運(yùn)行優(yōu)先級(jí)最高的就緒任務(wù)OSStartHighRdy()OSCtxSw()OSIntCtxSw()OSTickISR()OSStartHighRdy()函數(shù)是在OSStart()多任務(wù)啟動(dòng)之后,負(fù)責(zé)從最高優(yōu)先級(jí)任務(wù)的TCB控制中獲得該任務(wù)的堆棧指針SP,并通過(guò)SP依次將CPU現(xiàn)場(chǎng)恢復(fù)。這時(shí)系統(tǒng)就將控制權(quán)交給用戶創(chuàng)建的任務(wù)進(jìn)程,直到該任務(wù)被阻塞或都被其他更高優(yōu)先級(jí)的任務(wù)搶占CPU。該函數(shù)僅僅在多任務(wù)啟動(dòng)時(shí)被執(zhí)行一次,用來(lái)啟動(dòng)最高優(yōu)先級(jí)的任務(wù)執(zhí)行。移植該函數(shù)的原因是,它涉及將處理器寄存器保存到堆棧的操作。70OSStartHighRdyLDRR4,=NVIC_SYSPRI2;setthePendSVexception;priority設(shè)置PendSV優(yōu)先級(jí)

LDRR5,=NVIC_PENDSV_PRI STRR5,[R4]

MOVR4,#0;setthePSPto0forinitial;contextswitchcall使PSP等于0MSRPSP,R4

LDRR4,=OSRunning;OSRunning=TRUEMOVR5,#1STRBR5,[R4]LDRR4,=NVIC_INT_CTRL;triggerthePendSVexception;觸發(fā)軟件中斷

LDRR5,=NVIC_PENDSVSETSTRR5,[R4]CPSIEI;enableinterruptsatprocessor;level使能所有優(yōu)先級(jí)的中斷OSStartHangBOSStartHang71(2)OSCtxSw():任務(wù)優(yōu)先級(jí)切換函數(shù)

該函數(shù)由OS_TASK_SW()宏調(diào)用,OS_TASK_SW()由OSSched()函數(shù)調(diào)用,OSSched()函數(shù)負(fù)責(zé)任務(wù)之間的調(diào)度。OSCtxSw()函數(shù)的工作是,先將當(dāng)前任務(wù)的CPU現(xiàn)場(chǎng)保存到該任務(wù)的堆棧中,然后獲得最高優(yōu)先級(jí)任務(wù)的堆棧指針,并從該堆棧中恢復(fù)此任務(wù)的CPU現(xiàn)場(chǎng),使之繼續(xù)執(zhí)行,該函數(shù)就完了一次任切換。OSCtxSwPUSH{R4,R5}LDRR4,=NVIC_INT_CTRL;觸發(fā)軟件中斷

LDRR5,=NVIC_PENDSVSETSTRR5,[R4]POP{R4,R5}BXLR產(chǎn)生PendSV異常PendSV并沒(méi)有馬上執(zhí)行,因?yàn)镺S_TASK_SW()(實(shí)際是OSCtxSw())被調(diào)用前中斷是關(guān)閉的。PednSV只能在中斷使能后才能執(zhí)行。OS_TASK_SW()總是被OS_Sched()調(diào)用(見(jiàn)OS_CORE.C文件)72(3)OSInitCtxSw():中斷級(jí)的任務(wù)切換函數(shù)

該函數(shù)由OSIntExit()調(diào)用。由于中斷可能會(huì)使更高優(yōu)先級(jí)的任務(wù)進(jìn)入就緒態(tài),因此,為了讓更高優(yōu)先級(jí)的任務(wù)能立即運(yùn)行,在中斷服務(wù)子程序的最后,OSInitExit()函數(shù)會(huì)調(diào)用OSInitCtxSw()做任務(wù)切換。這樣做的目的主要是能夠盡快地讓高優(yōu)先級(jí)的任務(wù)得到響應(yīng),保證系統(tǒng)的實(shí)時(shí)性能。OSInitCtxSw()與OSCtxSw()都是用于任務(wù)切換函數(shù),其區(qū)別在于,在OSIntCtxSw()中無(wú)需再保存CPU寄存器,因?yàn)樵谡{(diào)用OSIntCtxSw()之前已發(fā)生了中斷,OSIntCtxSw()已將默認(rèn)的CPU寄存器保存到被中斷的任務(wù)堆棧中。OSIntCtxSwPUSH{R4,R5}LDRR4,=NVIC_INT_CTRL;觸發(fā)軟件中斷

LDRR5,=NVIC_PENDSVSETSTRR5,[R4]POP{R4,R5}BXLRNOPOSCtxSw()OSIntCtxSw()這兩個(gè)函最終都會(huì)觸發(fā)PendSV異常73OSPendSV()函數(shù)OSPendSV()是PendSV(可掛起中斷服務(wù))的中斷處理函數(shù),它負(fù)責(zé)μC/OS-II的全部上下文切換。這是ARMCortex-M3提倡的上下文切換方法。使用這程方法的好處理當(dāng)發(fā)生任何的異常時(shí),Cortex-m3自動(dòng)保存CPU的一半通用寄存器到預(yù)先指定的堆棧中,并且在退出異常前按順序恢復(fù)寄存器。OSPendSV()只需保存剩下的R4-R11寄存器并且調(diào)整好堆棧指針。這種方法速度快,充分體現(xiàn)了ARMCortex-M3的優(yōu)勢(shì),而且無(wú)論是任務(wù)還是異常均可觸發(fā)此函數(shù)切換上下文。注意使用前應(yīng)在Startup.S中申明。7475ARMCortex-M3任務(wù)切換示意圖76(4)OSTickISR():時(shí)鐘節(jié)拍中斷服務(wù)函數(shù)

時(shí)鐘節(jié)拍是特定的周期性中斷,是由硬件定時(shí)器產(chǎn)生的。時(shí)鐘節(jié)拍式中斷使得內(nèi)核可將任務(wù)延時(shí)若干個(gè)整數(shù)時(shí)鐘節(jié)拍,以及當(dāng)任務(wù)等待事件發(fā)生時(shí),提供等待超時(shí)的依據(jù)。時(shí)鐘節(jié)拍頻率越高,系統(tǒng)的額外開(kāi)銷(xiāo)越大。中斷間的時(shí)間間隔取決于不同的應(yīng)用。

OSTickISR()首先將CPU寄存器的值保存在被中斷任務(wù)的堆棧中,之后調(diào)用OSIntEnter()。隨后,OSTickISR()調(diào)用OSTimeTick,檢查所有處于延時(shí)等待狀態(tài)的任務(wù),判斷是否有延時(shí)結(jié)束就緒的任務(wù)。OSTickISR()最后調(diào)用OSIntExit()。如果在中斷中(或其他嵌套的中斷)有更高優(yōu)先級(jí)的任務(wù)就緒,并且當(dāng)前中斷為中斷嵌套的最后一層,那么OSIntExit()將進(jìn)行任務(wù)調(diào)度。774、移植C語(yǔ)言編寫(xiě)的6個(gè)與操作系統(tǒng)相關(guān)的函數(shù)OS_CPU_C.COS_CPU_C.C文件中包含6個(gè)和CPU相關(guān)的函數(shù),這6個(gè)函數(shù)為:

這些函數(shù)中,唯一必須移植的是任務(wù)堆棧初始化函數(shù)OSTaskStkInit()。這個(gè)函數(shù)在任務(wù)創(chuàng)建時(shí)被調(diào)用,負(fù)責(zé)初始化任務(wù)的堆棧結(jié)構(gòu)并返回新堆棧的指針stk。堆棧初始化工作結(jié)束后,返回新的堆棧棧頂指針。OSTaskStkInit()OSTaskDelHook()OSTaskSwHook()OSTaskStartHook()OSTimeHook()783.2基于ARM7的移植任務(wù)模式的取舍ARM7處理器核具有用戶、系統(tǒng)、管理、中止、未定義、中斷和快中斷七種

溫馨提示

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

最新文檔

評(píng)論

0/150

提交評(píng)論