嵌入式-3(new)_第1頁
嵌入式-3(new)_第2頁
嵌入式-3(new)_第3頁
嵌入式-3(new)_第4頁
嵌入式-3(new)_第5頁
已閱讀5頁,還剩133頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、嵌入式操作系統(tǒng)第三章 C/OS-II中的任務(rn wu)共一百三十八頁第3章 C/OS-II中的任務(rn wu)本部分的主要內容(nirng)包括:任務的基本概念任務代碼、任務控制塊和任務堆棧任務的優(yōu)先權任務就緒表結構及其操作任務切換及任務調度任務的創(chuàng)建、刪除、掛起、恢復和查詢C/OS-II的初始化和啟動2共一百三十八頁3.1 任務的基本概念3.1.1 任務及其內存(ni cn)結構在設計一個較為復雜的應用程序時,通常把一個大型任務分解成多個小任務,然后在計算機中通過運行這些小任務,最終達到完成大任務的目的。實時應用程序的設計過程包括如何把問題分割成多個任務。每個任務都是整個(zhngg)

2、應用程序的一部分,都被賦予一定的優(yōu)先級,有自己的一套CPU寄存器和??臻g。由于這種方法可以使系統(tǒng)并發(fā)地運行多個任務,從而提高處理器的利用率,加快程序的執(zhí)行速度,因此現(xiàn)代操作系統(tǒng)幾乎都是多任務操作系統(tǒng)。 3共一百三十八頁一個任務,也稱作一個線程,是一個簡單的程序,與大任務分割成的小任務對應的程序實體就叫做“任務”,而C/OS-II就是一個能對這些小任務的運行進行管理和調度的多任務操作系統(tǒng)。從代碼上看,C/OS-II的任務就是一個函數(shù)。而從任務的存儲結構上看,C/OS-II的任務由三個部分組成:任務程序代碼(函數(shù))、任務堆棧和任務控制塊。其中任務控制塊就是關聯(lián)了任務代碼的程序控制塊(TCB),它記

3、錄了任務的各個屬性;任務堆棧則用來保存任務的工作(gngzu)環(huán)境;任務程序代碼就是任務的執(zhí)行部分。 4共一百三十八頁PC5共一百三十八頁C/OS-II任務控制塊實質上就是2.4.2節(jié)中所介紹的具有二級結構的代碼控制塊,只不過用來指向代碼的指針是CPU程序指針(程序計數(shù)器)PC的副本。系統(tǒng)可以根據(jù)任務控制塊來了解代碼的相關信息,當然也就是能夠(nnggu)找到代碼。 注:任務控制塊通過任務堆棧和任務代碼間接的關聯(lián)起來6共一百三十八頁C/OS-II用任務控制塊鏈表對任務進行管理(gunl),如下圖所示:7共一百三十八頁C/OS-II的任務有兩種:用戶任務和系統(tǒng)任務。由應用程序設計者編寫的任務,叫

4、做用戶任務;由系統(tǒng)提供的任務叫做系統(tǒng)任務。用戶任務是為了(wi le)解決應用問題而編寫的;系統(tǒng)任務是為應用程序提供某種服務或為系統(tǒng)本身服務的。目前,在C/OS-II中,最多可以含有64個任務(包括用戶任務和系統(tǒng)任務)。 8共一百三十八頁 C/OS II 支持64個任務,每個任務有一個特定的優(yōu)先級。 任務的優(yōu)先級別用數(shù)字表示(biosh),0表示的任務的優(yōu)先級最高,數(shù)字越大表示的優(yōu)先級越低。 通過常數(shù)OS_LOWEST_PRIO (在OS_CFG.H中)定義系統(tǒng)的最低優(yōu)先級別,同時限定系統(tǒng)能容納的最多任務數(shù)量。 建議用戶不要使用優(yōu)先級為0、1、2、3、OS_LOWEST_PRIO-3、 OS_

5、LOWEST_PRIO-2、 OS_LOWEST_PRIO-1、 OS_LOWEST_PRIO-0的任務。最低的兩個已被目前版本的系統(tǒng)占用,將來版本可能會用到其它的。 9共一百三十八頁3.1.2 任務(rn wu)的狀態(tài) C/OS-II是按照系統(tǒng)中只有一個CPU來設計的,在這種系統(tǒng)中,一個具體時刻只會有一個任務占用,及處在運行狀態(tài),而其他任務只能處在其他狀態(tài)。C/OS-II系統(tǒng)中的任務共有5種狀態(tài): 睡眠態(tài)(DORMANT):任務在沒有(mi yu)被配備任務控制塊或被剝奪了任務控制塊時的狀態(tài)叫作任務的睡眠態(tài)。就緒態(tài)(READY):如果系統(tǒng)為任務配備了任務控制塊且在任務就緒表中進行了就緒登記,

6、則任務就具備了運行的充分條件,這時的任務的狀態(tài)叫就緒態(tài)。10共一百三十八頁 運行態(tài)(RUNNING):處于就緒態(tài)的任務如果經調度器判斷獲得了CPU的使用權,則任務就進入運行態(tài)。任何時刻只能有一個任務處于運行態(tài)。等待態(tài)(WAITING):正在運行的任務,需要等待一段時間或需要等待一個事件(shjin)發(fā)生再運行時,該任務就會把CPU的使用權讓給其他任務而使任務進入waiting狀態(tài)。 注:進入waiting的狀態(tài)有可能是因為延時,有可能是被掛起,有可能是等待的資源未獲得,總之,uC/OS將所有的已經注冊了的但未就緒的任務歸為waiting態(tài)。被中斷態(tài)(ISR):正在運行的任務是可以被中斷的,除非

7、該任務將中斷關了,或者uC/OS-將中斷關了。被中斷了的任務就進入了中斷服務態(tài)(ISR)。當所有的任務都在等待事件發(fā)生或等待延遲時間結束,uC/OS-執(zhí)行空閑任務(idle task),執(zhí)行OSTaskIdle() 函數(shù)。 11共一百三十八頁在系統(tǒng)的管理下,一個任務可以(ky)在5個不同的狀態(tài)之間發(fā)生轉換。其轉換關系如圖所示 12共一百三十八頁線上的函數(shù)作用:狀態(tài)遷移依靠這些(zhxi)函數(shù)完成13共一百三十八頁3.1.3 用戶任務代碼的一般(ybn)結構1. 用戶任務代碼的一般結構 根據(jù)嵌入式系統(tǒng)任務的工作特點,任務的執(zhí)行代碼通常是一個無限(wxin)循環(huán)結構(對于一些一次性任務例外),并且

8、在這個循環(huán)中可以響應中斷,這種結構也叫做超循環(huán)結構。例3-1就是一個具有超循環(huán)結構的任務的示意性代碼。 14共一百三十八頁例3-1 一個用C語言編寫的任務void MyTask(void * pdata)for( ; ; )可以被中斷的用戶代碼;OS_ENTER_CRITICAL();/進入臨界段(關中斷)不可以被中斷的用戶代碼;OS_EXIT_CRITICAL();/退出臨界段(開中斷)可以被中斷的用戶代碼;從程序的角度來看,一個C/OS-II任務的代碼就是(jish)一個C語言函數(shù)。之所以把任務的參數(shù)定義成一個void類型的指針,是為了傳遞各種不同類型的數(shù)據(jù)。15共一百三十八頁為了有效的對

9、中斷進行控制,在任務的代碼里可使用uC/OS-II定義的宏OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()來控制何時響應中斷,何時屏蔽中斷。這兩個宏之間的代碼時是不會響應中斷的,這種受保護的代碼段叫臨界段。代碼的臨界段也稱為臨界區(qū),指處理時不可分割的代碼。一旦這部分代碼開始(kish)執(zhí)行,則不允許任何中斷打入。為確保臨界段代碼的執(zhí)行不被中斷,在進入臨界段之前必須關中斷,而臨界段代碼執(zhí)行完后,要立即開中斷。 16共一百三十八頁2用戶應用程序的一般結構(jigu)從程序代碼來看,用戶任務就是一個C語言函數(shù),但這個函數(shù)不是自主函數(shù)main()調用的函數(shù),在系統(tǒng)中它與主函

10、數(shù)main()處于平等的地位,它們何時被運行以及何時被終止是由操作系統(tǒng)來調度的。但要注意,main()畢竟是一個應用程序的主函數(shù),是程序運行的入口點,所以雖然它不調用任務,但要負責任務的創(chuàng)建并將它們交給系統(tǒng),至于何時運行它們,則與主函數(shù)無關。 17共一百三十八頁用戶應用程序的代碼大體如下(rxi):例3-2 用戶應用程序的結構void MyTask1(void * pdata)/定義用戶任務1for( ; ; )void MyTask2(void * pdata)/定義用戶任務2for( ; ; )18共一百三十八頁void MyTask3(void * pdata)/定義用戶任務3for(

11、; ; )void main()OSInit();/初始化C/OS-IIOSTaskCreate(MyTask1,);/創(chuàng)建(chungjin)用戶任務1OSTaskCreate(MyTask2,);/創(chuàng)建用戶任務2OSTaskCreate(MyTask3,);/創(chuàng)建用戶任務3OSStart();/啟動C/OS-II19共一百三十八頁其中(qzhng),OSTaskCreate()是C/OS-II提供的用來創(chuàng)建任務的函數(shù);OSStart()啟動C/OS-II的函數(shù)。系統(tǒng)被啟動后,任務就由操作系統(tǒng)來管理和調度了。 20共一百三十八頁3.1.4 系統(tǒng)(xtng)任務作為管理者,操作系統(tǒng)除了要管理用

12、戶任務之外,可能會有一些內部事務需要處理,最起碼要有一個沒有用戶任務可執(zhí)行時需要做的事情,因為計算機是不能停下來的。為了與用戶任務相區(qū)別,這種系統(tǒng)自己(zj)所需要的任務叫做系統(tǒng)任務。C/OS-II預定義了兩個系統(tǒng)任務:空閑任務和統(tǒng)計任務。其中空閑任務是每個應用程序必須使用的,而統(tǒng)計任務則是應用程序可以根據(jù)實際需要來選擇使用的。 21共一百三十八頁1. 空閑任務C/OS-II總要建立一個空閑任務(idle task),這個任務在沒有其他任務進入就緒狀態(tài)時投入運行。這個空閑任務OSTaskIdle()永遠設為最低優(yōu)先級,即OS_LOWER_PRIO。空閑任務OSTaskIdle()的代碼如下:v

13、oid OSTaskIdle( void * pdata) pdata = pdata; /防止某些編譯器報錯 for(;) OS_ENTER_CRITICAL();/關閉中斷 OSIdleCtr+; /計數(shù) OS_EXIT_CRITICAL(); /開放中斷 C/OS-II規(guī)定,一個用戶應用程序必須使用這個空閑任務,而且(r qi)這個任務是不能用程序來刪除的。22共一百三十八頁2統(tǒng)計任務 C/OS-II提供的另一個系統(tǒng)任務就是統(tǒng)計任務OSTaskStat( ) OSTaskStat( )每秒運行1次,計算(j sun)CPU利用率,即告訴用戶應用程序使用了多少CPU時間,用百分比表示,精確

14、度為1%。 如果將系統(tǒng)頭文件OS_CFG.H中的系統(tǒng)配置常數(shù)OS_TASK_STAT_EN設置為1,統(tǒng)計任務就會在操作系統(tǒng)初始化函數(shù)OSInit( )中調用OS_InitTaskStat()函數(shù)創(chuàng)建。23共一百三十八頁 在系統(tǒng)調用(dioyng)多任務啟動函數(shù)OSStart( )之前,用戶初始代碼中必須先建立至少一個用戶任務(如TaskStart),如果應用程序打算使用統(tǒng)計任務,需要在TaskStart任務中調用函數(shù) OSStatInit( )對統(tǒng)計任務進行初始化。之后再建立應用程序中的其他任務。 應該在用戶任務中(第一個任務)啟動時鐘節(jié)拍。因為用戶不希望在多任務還沒有開始時就收到時鐘節(jié)拍中斷

15、24共一百三十八頁void main (void)OSInit(); /初 始化uC/OS-II /* 創(chuàng)建用戶起始任務(以TaskStart()作為起始任務,也可以創(chuàng)建多個任務)*/OSStart(); /開 始多任務調度void TaskStart (void *pdata)/* 在這里安裝并啟動uC/OS-II的時鐘節(jié)拍(jipi) */OSStatInit(); / 初始化統(tǒng)計任務 /* 創(chuàng)建用戶應用程序任務 */for (;) /* 這里是TaskStart()的代碼 */ OSTimeDly(10); /調用該函數(shù)的任務將自己延時10個時鐘并執(zhí)行一次任務調度 25共一百三十八頁3.

16、1.5 任務(rn wu)的優(yōu)先權及優(yōu)先級別uC/OS-II分為64個優(yōu)先級別,每一個級別都用一個數(shù)字表示。數(shù)字0的級別最高,數(shù)字越大優(yōu)先級別越低。通常,一個應用程序的任務數(shù)小于64,用戶可根據(jù)應用程序的需要,在OS_CFG.H中設置OS_LOWEST_PRIO,即定義了可供使用的優(yōu)先級別共OS_LOWEST_PRIO +1個。固定地,系統(tǒng)總是把最低優(yōu)先級別自動賦給空閑(kngxin)任務,如果系統(tǒng)中還有統(tǒng)計任務,則其優(yōu)先級別為OS_LOWEST_PRIO -1。因此用戶任務可以使用的優(yōu)先級別是0,1,2,.,OS_LOWEST_PRIO-2,共OS_LOWEST_PRIO-1個 26共一百三

17、十八頁例:如果(rgu)希望應用程序中任務的優(yōu)先級別為28個,則表示最低優(yōu)先級別的常數(shù)OS_LOWEST_PRIO值應該是多少?如果應用程序中使用了系統(tǒng)提供的空閑任務和統(tǒng)計任務,則該應用程序最多可以安排多少個任務? 27共一百三十八頁答:表示最低優(yōu)先級別的常數(shù)OS_LOWEST_PRIO值應該為27,優(yōu)先級別分別(fnbi)為0,1,2,3,.,27;由于系統(tǒng)空閑任務占用了優(yōu)先級別27,統(tǒng)計任務占用了優(yōu)先級別26,則應用程序中最多可以安排優(yōu)先級別分別為0,1,2,.,25的26個任務。28共一百三十八頁給某一個(y )用戶任務的定義優(yōu)先級別,需要在調用系統(tǒng)函數(shù)OSTaskCreate()來創(chuàng)建

18、任務時,用該函數(shù)的第4個參數(shù)prio來指定。 由于每個任務都具有惟一的優(yōu)先級別,因此C/OS-II通常也用任務的優(yōu)先級別來作為這個任務的標識。 29共一百三十八頁3.2 任務(rn wu)堆棧任務堆棧是任務的重要組成部分。所謂堆棧,就是在存儲器中按數(shù)據(jù)“后進先出(LIFO)”的原則組織(zzh)的連續(xù)存儲空間。為了滿足任務切換和響應中斷時保存CPU寄存器中的內容及任務調用其他函數(shù)時的需要,每個任務都有自己的??臻g。所有C/OS-II任務的任務控制塊中都含有一個指向該任務堆棧的指針。30共一百三十八頁C/OS-II中堆棧的數(shù)據(jù)類型為為OS_STK,在文件OS_CPU.H中定義: typedef

19、unsigned int OS_STK; /該類型長度(chngd)為16位 這樣,在應用程序中定義任務堆棧的棧區(qū)就非常簡單,即定義一個OS_STK類型的一個數(shù)組即可。例如:#define TASK_STK_SIZE 512 /定義堆棧的長度(1024字節(jié))OS_STK TaskStkTASK_STK_SIZE; /定義一個數(shù)組來作為任務堆棧當調用函數(shù)OSTaskCreate()來創(chuàng)建一個任務時,把數(shù)組的指針傳遞給函數(shù)OSTaskCreate()中的堆棧棧頂參數(shù)ptos,就可以把該數(shù)組與任務關聯(lián)起來而成為該任務的任務堆棧。 31共一百三十八頁例3-4 創(chuàng)建任務函數(shù)OSTaskCreate()的

20、原型如下:INT8U OSTaskCreate( void (*task)(void *pd), /指向任務的指針 void *pdata, /傳遞給任務的參數(shù) OS_STK *ptos, /任務堆棧棧頂?shù)闹羔?INT8U prio ); /指定任務優(yōu)先級別的參數(shù) );使用例3-1的代碼來作為任務代碼來創(chuàng)建一個(y )任務MyTask,任務堆棧的長度為128字節(jié),優(yōu)先級別為20,任務參數(shù)pdata的實參為MyTaskAgu。試寫出main()函數(shù)的代碼。 32共一百三十八頁#define MyTaskStkN 64OS_STK MyTaskStkMyTaskStkN ;void main(vo

21、id)OSTaskCreate(MyTask,/任務的指針&MyTaskAgu,/傳遞給任務的參數(shù)(cnsh)&MyTaskStkMyTaskStkN-1,/任務堆棧棧頂?shù)刂?0);/任務的優(yōu)先級別33共一百三十八頁堆棧(duzhn)的增長方向是隨系統(tǒng)所使用的處理器不同而不同。因此在使用函數(shù)OSTaskCreate() 創(chuàng)建任務時,一定要注意所使用的處理器對堆棧增長方向的支持是向上的還是向下的。 34共一百三十八頁上一練習時假設使用了支持堆棧向下增長方式的處理器設置參數(shù)ptos。如果使用的處理器支持堆棧的增長方向向上,則應該為: OSTaskCreate( MyTask, &MytaskAgu

22、, &MyTaskStk0, 20);為了提高應用程序的移植性,在編寫代碼時可兼顧兩種情況,利用OS_CFG.H文件中的常數(shù)OS_STK_GROWTH 作為選擇開關,使用戶可通過定義該常數(shù)的值來選擇相應代碼段,以適應不同的堆棧增長方向的需要(xyo)。試改寫上一練習代碼。35共一百三十八頁#define MyTaskStkN 64OS_STK MyTaskStkMyTaskStkN ;void main(void) # if OS_STK_GROWTH=1 OSTaskCreate( MyTask, /任務的指針 &MyTaskAgu, /傳遞給任務的參數(shù) &MyTaskStkMyTaskSt

23、kN-1, /任務堆棧(duzhn)棧頂?shù)刂?20); /任務的優(yōu)先級別#else OSTaskCreate( MyTask, /任務的指針 &MyTaskAgu, /傳遞給任務的參數(shù) &MyTaskStk0, /任務堆棧棧頂?shù)刂?20); /任務的優(yōu)先級別#endif 36共一百三十八頁3.2.2 任務(rn wu)堆棧的初始化當CPU啟動運行一個任務時,CPU的各寄存器總是需要預置一些初始數(shù)據(jù),例如指向(zh xin)任務的指針、任務堆棧指針、程序狀態(tài)字等。那么,系統(tǒng)啟動任務時,CPU從何處可以獲得這些數(shù)據(jù)呢?最方便的方法就是讓CPU從這個任務的任務堆棧里獲得這些數(shù)據(jù)。C/OS-II在創(chuàng)建

24、任務函數(shù)OSTaskCreat ()中通過調用任務堆棧初始化函數(shù)OSTaskStkInit ()來完成任務堆棧初始化工作的,其原型如下: 37共一百三十八頁OS_STK * OSTaskStkInit ( void ( * task)(void * pd), void * pdata, OS_STK * ptos, INIT16U opt ); 通常用戶不會直接接觸到這個函數(shù),該函數(shù)由C/OS-II所提供的任務創(chuàng)建(chungjin)函數(shù)OSTaskCreate()來調用。由于各處理器的寄存器及對堆棧的操作方式不同,因此該函數(shù)需要用戶在進行C/OS-II的移植時,按所使用的處理器由用戶來編寫。

25、 38共一百三十八頁3.3任務(rn wu)控制塊(TCB)及任務控制塊鏈表C/OS-II用來記錄任務的堆棧指針、任務的當前狀態(tài)、任務的優(yōu)先級別等一些與任務管理有關的屬性(shxng)的表就叫做任務控制塊。C/OS-II把系統(tǒng)所有任務的控制塊鏈接為兩條鏈表,并通過它們管理各個任務。39共一百三十八頁 一旦任務(rn wu)建立,一個任務(rn wu)控制塊OS_TCB就被賦值。 任務控制塊是一個數(shù)據(jù)結構,保存該任務的相關參數(shù),包括任務堆棧指針,任務的當前狀態(tài),任務的優(yōu)先級等。 任務CPU使用權被剝奪時,TCB保存該時刻任務狀態(tài);任務重新得到CPU控制權時,TCB確保任務從當時被中斷的那一點絲毫

26、不差地繼續(xù)執(zhí)行。 OS_TCB全部駐留在RAM中。 任務控制塊就相當于一個任務的身份證,沒有任務控制塊的任務是不能被系統(tǒng)承認和管理的。3.3.1 任務控制(kngzh)塊的結構40共一百三十八頁任務控制塊的結構的定義如 p52所示任務控制塊結構的主要成員(需要熟知): typedef struct os_tcb OS_STK *OSTCBStkPtr; /指向任務堆棧棧頂?shù)闹羔?struct os_tcb *OSTCBNext; /指向后一個任務控制塊的指針 struct os_tcb *OSTCBPrev; /指向前一個任務控制塊的指針 INT16U OSTCBDly; /任務等待的時限(s

27、hxin)(節(jié)拍數(shù)) 當需要把任務延時若干時鐘節(jié)拍時,或者需要把任務掛起一段時間以等待某事件的發(fā)生時需要用到這個變量。如果這個變量為0,表示任務不延時,或者表示等待事件發(fā)生的時間沒有限制 。 INT8U OSTCBStat; /任務的當前狀態(tài)標志 INT8U OSTCBPrio; /任務的優(yōu)先級別 OS_TCB;41共一百三十八頁其中OSTCBStat:任務狀態(tài)字,可取下列值:OS_STAT_RDY: 處于就緒狀態(tài)OS_STAT_SEM: 處于等待信號量狀態(tài)OS_STAT_MBOX:處于等待郵箱狀態(tài)OS_STAT_Q: 處于等待消息(xio xi)隊列狀態(tài)OS_STAT_SUSPEND:處于被

28、掛起狀態(tài)OS_STAT_MUTEX:處于等待互斥信號量狀態(tài)42共一百三十八頁3.3.2 任務(rn wu)控制塊鏈表兩條鏈表來管理任務控制塊: 空任務塊鏈表(所有(suyu)任務控制塊還沒有分配給任務),是在應用程序調用函數(shù)OSInit( )對系統(tǒng)進行初始化時建立的。 任務塊鏈表(所有任務控制塊已經分配給任務),是在調用函數(shù)OSTaskCreate( )創(chuàng)建任務時建立的。建立任務控制塊鏈表的具體做法是,從空鏈表摘取一個空任務控制塊,然后填充上任務屬性后再形成新的鏈表。43共一百三十八頁系統(tǒng)在調用函數(shù)OSInit()對C/OS-II系統(tǒng)進行初始化時,先在RAM中建立一個OS_TCB結構類型的數(shù)組

29、OSTCBTbl ,每個數(shù)組元素(yun s)就是一個任務控制塊,然后把這些控制塊鏈接成一個如圖所示的鏈表。由于鏈表中的這些控制塊還沒有與具體任務相關聯(lián),因此這個鏈表叫做空任務塊鏈表OSTCBFreeList。44共一百三十八頁每當應用程序調用系統(tǒng)函數(shù)OSTaskCreate()創(chuàng)建一個任務時,系統(tǒng)就會將任務控制塊鏈表頭指針OSTCBFreeList指向的任務控制塊分配給該任務。在給任務控制塊中的各成員賦值后,就按任務控制塊鏈表的頭指針OSTCBList將其加入到任務控制塊鏈表中。下圖是在上圖空任務控制塊鏈表基礎上,應用程序創(chuàng)建了兩個用戶任務并使用了兩個系統(tǒng)任務(空閑任務和統(tǒng)計任務)的情況時,

30、空任務塊鏈表和任務塊鏈表的結構示意圖(圖中陰影(ynyng)區(qū)域為任務塊鏈表)。 45共一百三十八頁46共一百三十八頁3.3.3 任務(rn wu)控制塊初始化當用戶程序調用函數(shù)OSTaskCreate() 創(chuàng)建一個任務時,這個(zh ge)函數(shù)會調用系統(tǒng)函數(shù)OSTCBInit() 來為任務控制塊進行初始化。任務控制塊初始化函數(shù)OSTCBInit()做三件事:1、從空任務控制塊鏈表中獲取一個任務控制塊;2、用任務的屬性值對任務控制塊各個成員進行賦值;3、把這個任務控制塊鏈入到任務控制塊使用鏈表的頭部。47共一百三十八頁初始化任務控制(kngzh)塊函數(shù)OSTCBInit() 的原型如下:INT

31、8U OSTCBInit(INT8U Prio,/任務的優(yōu)先級別,保存在OSTCBPrio中OS_STK *ptos, /任務堆棧棧頂指針,保存在OSTCBStkPtr中OS_STK *pbos, /任務堆棧棧底指針,保存在OSTCBStkBottom中INT16U id, /任務的標示符,保存在OSTCBId中INT16U stk_size, /任務堆棧的長度,保存在OSTCBStkSize中void *pext, /任務控制塊的擴展指針,保存在OSTCBExtPtr中INT16U opt /任務的控制塊的選擇項,保存在OSTCBOpt中);48共一百三十八頁3.4 任務(rn wu)就緒表

32、及任務(rn wu)調度多任務操作系統(tǒng)的核心:任務調度。調度定義:就是通過一個算法在多個任務中確定哪個任務來運行(ynxng)。做這項工作的就是調度器。任務調度的思想:總是讓優(yōu)先級最高的就緒任務處于運行狀態(tài)。C/OS-II進行任務調度的依據(jù):任務就續(xù)表。49共一百三十八頁至于什么是任務就緒表?可以這樣理解,為了能使系統(tǒng)清楚地知道系統(tǒng)中哪些任務已經就緒,哪些還沒有(mi yu)就緒, C/OS-II在RAM中設立了一個記錄表,系統(tǒng)中的每個任務都在這個表占據(jù)一個位置,并用這個位置的狀態(tài)( 1或者0)來表示任務是否處于就緒狀態(tài)。這個表就叫做任務就緒表。 50共一百三十八頁3.4.1 任務就緒(jix

33、)表結構每個就緒的任務都放入就緒表中(ready list)中,就緒表用兩個變量(binling)表示:OSRdyGrp、OSRdyTbl 。在OSRdyGrp中,任務按優(yōu)先級分組,8個任務為一組。OSRdyGrp中的每一位表示8組任務中每一組是否有進入就緒態(tài)的任務。任務進入就緒態(tài)時,就緒表OSRdyTbl 中的相應元素的相應位也置為1。OSRdyGrp和OSRdyTbl 之間的關系見下圖,它們之間的關系是按照以下規(guī)則給出的:當OSRdyTbl0中的任何一位是1時,OSRdyGrp的第0位置1;當OSRdyTbl1中的任何一位是1時,OSRdyGrp的第1位置1;當OSRdyTbl2中的任何一

34、位是1時,OSRdyGrp的第2位置1;當OSRdyTbl3中的任何一位是1時,OSRdyGrp的第3位置1;51共一百三十八頁52共一百三十八頁就緒表OSRdyTbl 數(shù)組的大小取決于OS_LOWEST_PR1O(見文件OS_CFG.H)。當用戶的應用程序中任務數(shù)目比較少時,減少OS_LOWEST_PR1O 的值可以(ky)降低C/OS-對RAM(數(shù)據(jù)空間)的需求量。那么如何根據(jù)任務的優(yōu)先級別查找任務在就緒表的位置呢? 從圖中可以看出,由于優(yōu)先級別是一個單字節(jié)的數(shù)字,而且最大值不會超過63,即二進制00111111,因此,可以把優(yōu)先級別看成是一個6位的二進制數(shù),這樣就可以用高3位(Y、Y、Y

35、)來指明變量OSRdyGrp的具體數(shù)據(jù)位,并用來確定就緒表數(shù)組元素的下標;用低3位(X、X、X)來指明該數(shù)組元素的具體數(shù)據(jù)位。 53共一百三十八頁 例3-5:已知某一個已經就緒的任務優(yōu)先級別為prio=30,試判斷(pndun)應該在就緒表的哪一位置上置1。 答:30的二進制形式為00011110,其低6位為011110,于是可知應該把變量OSRdyGrp的D3位置1 , 同時要在OSRdyTbl3 的D6位上置1 。54共一百三十八頁根據(jù)就緒表確定(qudng)最高優(yōu)先級兩個關鍵:優(yōu)先級數(shù)分解為高三位和低三位分別確定;高優(yōu)先級有著小的優(yōu)先級號 。55共一百三十八頁3.4.2 對任務(rn w

36、u)就緒表的操作系統(tǒng)對于就緒表主要有三個操作(cozu):登記、注銷和從就緒表的就緒任務中得知具有最高優(yōu)先級任務的標識(優(yōu)先級prio)。 56共一百三十八頁1. 登記登記:指的是當某個任務處于就緒狀態(tài)(zhungti)時,系統(tǒng)將該任務登記在任務就緒表中,即在就續(xù)表中將該任務的對應位置1。在程序中,可用類似于下面的代碼把優(yōu)先級為prio的任務置為就緒態(tài):OSRdyGrp | = OSMapTblprio3;OSRdyTblprio3 | = OSMapTblprio & 0 x07;其中,OSMapTbl 是C/OS-II為加快運算速度定義的一個數(shù)組,各元素為:OSMapTbl0 = 0000

37、 0001BOSMapTbl1 = 0000 0010BOSMapTbl2 = 0000 0100BOSMapTbl3 = 0000 1000BOSMapTbl4 = 0001 0000BOSMapTbl5 = 0010 0000BOSMapTbl6 = 0100 0000BOSMapTbl7 = 1000 0000B57共一百三十八頁例1:使優(yōu)先級為12的任務進入就緒(jix)狀態(tài),12=1100b, OSRdyGrp|= OSMapTblprio 3 |= OSMapTbl1 |= 00000010OSRdyTblprio 3|= OSMapTblprio & 0 x07 |= OSMap

38、Tbl100b |= OSMapTbl4 |= 00010000即OSRdyGrp的第1位置1,OSRdyTbl1的第4位置158共一百三十八頁59共一百三十八頁例2:使優(yōu)先級為21的任務進入就緒(jix)態(tài),21=10 101b,OSRdyGrp|= OSMapTblprio 3 |= OSMapTbl10b= OSMapTbl2 |= 00000100OSRdyTblprio 3|= OSMapTblprio & 0 x07 |= OSMapTbl101b |= OSMapTbl5 |= 00100000即OSRdyGrp的第2位置1,OSRdyTbl2的第5位置160共一百三十八頁61共

39、一百三十八頁2. 注銷注銷:指的是當某個任務需要脫離就緒狀態(tài)時,系統(tǒng)在就緒表中將該任務的對應位置0。如果要使一個優(yōu)先級別為prio的任務脫離就緒狀態(tài),則可使用如下代碼:If(OSRdyTblprio3&= OSMapTblprio & 0 x07)=0)OSRdyGrp&= OSMapTblprio3; 脫離就緒態(tài):將任務就緒表OSRdyTblprio3相應(xingyng)元素的相應(xingyng)位清零,而且當OSRdyTblprio3中的所有位都為零時,即全組任務中沒有一個進入就緒態(tài)時,OSRdyGrp的相應位才為零。 62共一百三十八頁例:使優(yōu)先級為12的任務(rn wu)脫離就緒表

40、 答: 欲使優(yōu)先級為12的任務進入就緒態(tài) 優(yōu)先級為12,即00001100BOSRdyGrp | = OSMapTblprio 3 ; (OSMapTbl1 = 0000 0010)OSRdyTbl1 | = OSMapTblprio &0 x07 ; (OSMapTbl4 = 0001 0000) 欲使優(yōu)先級為12的任務脫離就緒態(tài) OSMapTblprio & 0 x07 = OSMapTbl4 = 11101111 OSMapTblprio 3 = OSMapTbl1 = 11111101如果OSRdyTblprio 3 &= OSMapTblprio & 0 x07 = 0 (該行所有任

41、務都是非就緒態(tài))則OSRdyGrp = OSRdyGrp & OSMapTblprio 3 = 063共一百三十八頁064共一百三十八頁3找出進入就緒態(tài)的優(yōu)先級最高的任務 從任務就緒表中獲取優(yōu)先級別(jbi)最高的就緒任務可用如下代碼:y = OSUnMapTblOSRdyGrp;/獲得優(yōu)先級別的D5、D4、D3位x = OSUnMapTblOSRdyTbly;/獲得優(yōu)先級別的D2、D1、D0位Prio =(y3)+x;/獲得就緒任務的優(yōu)先級別 或y = OSUnMapTblOSRdyGrp;Prio = (INT8U)(y3)+OSUnMapTblOSRdyTbly);65共一百三十八頁該代

42、碼執(zhí)行后,得到的是最高優(yōu)先級就緒(jix)任務的優(yōu)先級別。其中,OSUnMapTbl同樣是C/OS-II為加快運算速度定義的一個數(shù)組,共有256個元素,其定義如下:INT8U const OSUnMapTbl = 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /0 x00 to 0 x0F 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /0 x10 to 0 x1F 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /0 x20 to 0 x2F 4

43、, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /0 x30 to 0 x3F 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /0 x40 to 0 x4F 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /0 x50 to 0 x5F 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /0 x60 to 0 x6F 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1,

44、0, /0 x70 to 0 x7F 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /0 x80 to 0 x8F 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /0 x90 to 0 x9F 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /0 xA0 to 0 xAF 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /0 xB0 to 0 xBF 6, 0, 1, 0, 2, 0, 1, 0, 3

45、, 0, 1, 0, 2, 0, 1, 0, /0 xC0 to 0 xCF 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /0 xD0 to 0 xDF 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /0 xE0 to 0 xEF 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 /0 xF0 to 0 xFF; 66共一百三十八頁例:已知OSRdyGrp=01101000b, OSRdyTbl3=11100100b,找出進入就緒態(tài)的優(yōu)先級最高的任務

46、(rn wu) OSRdyGrp=01101000b=0 x68,查OSUnMapTbl0 x68得到的值是3,y=3。 OSRdyTbl3=11100100b=0 xE4,則OSUnMapTbl0 xE4的值是2,x=2。 Prio= (y 3) + x=3*8+2=26。67共一百三十八頁68共一百三十八頁例2 已知OSRdyGrp=00100100b, OSRdyTbl2=00010010b,找出進入就緒(jix)態(tài)的優(yōu)先級最高的任務y=OSUnMapTblOSRdyGrp=OSUnMapTbl100100b =OSUnMapTbl0 x24=2x = OSUnMapTblOSRdyTb

47、ly= OSUnMapTblOSRdyTbl2 =OSUnMapTbl00010010b =OSUnMapTbl0 x12=1prio = (y 3) + x =(23)+1=17 69共一百三十八頁70共一百三十八頁3.4.3 任務(rn wu)的調度1. 調度器的主要工作任務切換:在多任務系統(tǒng)中,令CPU中止當前正在運行的任務而去運行另一個任務的工作。任務調度:按某種規(guī)則進行任務切換的工作。調度的發(fā)生條件:系統(tǒng)或用戶任務調用系統(tǒng)函數(shù)或者(huzh)執(zhí)行中斷服務程序結束時。任務調度由任務調度器完成,調度器主要工作:1)在任務就緒表中查找具有最高優(yōu)先級別的就緒任務。2)實現(xiàn)任務切換。C/OS-

48、II有兩種調度器:任務級調度器(由OSSched() 實現(xiàn))、中斷級調度器(由OSIntExt ()實現(xiàn))。任務切換的兩個步驟:1)獲得待運行任務的TCB指針。2)進行斷點數(shù)據(jù)的切換。 71共一百三十八頁2. 獲得待運行任務的TCB指針由于操作系統(tǒng)是通過任務的任務控制塊TCB來管理任務的,因此調度器真正實施任務切換之前的主要(zhyo)工作就是要獲得待運行任務的任務控制塊指針和當前任務的任務控制塊指針。 任務級的調度函數(shù)OSSched( )代碼如下 :void OSSched (void)INT8U y;OS_ENTER_CRITICAL(); /關中斷if (OSLockNesting |

49、OSIntNesting) = 0) /如果調用來自中斷服務程序,或者至少調用了一次給任務調度上鎖函數(shù),任務調度函數(shù)將退出 72共一百三十八頁y = OSUnMapTblOSRdyGrp;OSPrioHighRdy = (INT8U)(y 0。 74共一百三十八頁2)首先從任務就緒表中查得的最高優(yōu)先級別就緒任務的優(yōu)先級別OSPrioHighRdy;然后在確認(qurn)了這個就緒任務不是當前正在運行的任務(OSPrioCur是存放正在運行任務的優(yōu)先級別的變量)的條件下,用OSPrioHighRdy作為下標去訪問數(shù)組OSTCBPrioTbl,把數(shù)組元素OSTCBPrioTblOSPrioHigh

50、Rdy的值(即待運行就緒任務的任務控制塊指針)付給指針變量OSTCBHighRdy。于是可以依據(jù)OSTCBHighRdy和OSTCBCur這兩個分別指向待運行任務控制塊和當前任務控制塊的指針在宏OS_TASK_SW( )中實施任務切換了。 75共一百三十八頁3. 任務切換(qi hun)OS_TASK_SW( )任務級的任務切換需完成以下2步操作:將被掛起任務的處理器寄存器推入堆棧將較高優(yōu)先級任務的寄存器值從堆棧中恢復到寄存器中任務級的任務切換由OS_TASK_SW( )宏完成.#define OS_TASK_SW( ) OSCtxSw( )76共一百三十八頁下圖1示意C/OS-II在調用OS

51、_TASK_SW( )之前一些(yxi)變量和數(shù)據(jù)結構的狀況。為了便于討論,構造了一個假想的CPU,該CPU有8個寄存器:1個堆棧指針(SP);1個程序計數(shù)器(PC);1個處理器狀態(tài)寄存器(PSW);4個通用寄存器(R1,R2,R3及R4)。 77共一百三十八頁(1)(3)(2)(5)(4)78共一百三十八頁下圖2示意調用OS_TASK_SW( )以及保存被掛起任務的CPU寄存器之后,一些(yxi)變量和數(shù)據(jù)結構的狀況:保存當前任務CPU寄存器的值 79共一百三十八頁(1) 調用含有中斷指令的函數(shù)OS_TASK_SW( ),強制處理器保存PSW和PC的當前值(2) 軟中斷的執(zhí)行從保存通用寄存器

52、開始,順序是R1,R2,R3,R4(3) 然后堆棧指針(zhzhn)寄存器被保存在當前任務的OS_TCB中。此時,CPU的SP寄存器和OSTCBCurOSTCBStkPtr都指向當前任務堆棧的同一位置80共一百三十八頁下圖3示意(shy)執(zhí)行任務切換最后一段代碼之后變量和數(shù)據(jù)結構的狀況:重新裝入要運行的任務81共一百三十八頁(1) 由于(yuy)新的當前任務是將要重新開始運行的任務,任務切換代碼將OSTCBHighRdy復制到OSTCBCur(2) 從OS_TCB中找出將要重新開始運行的任務的堆棧指針(在OSTCBHighRdyOSTCBStkPtr中),裝入CPU的SP寄存器中。此時,SP寄

53、存器指向堆棧中存有寄存器R4值的位置(3) 按相反的方向從堆棧中彈出通用寄存器(4) 通過執(zhí)行中斷返回指令,PC和PSW的值裝回到CPU中。此時,由于程序計數(shù)器PC的值變了,重新開始運行的任務代碼從PC指向的那一點開始運行,于是切換到新任務代碼的過程完成了。82共一百三十八頁83共一百三十八頁任務切換OS_TASK_SW()的代碼void OSCtxSw(void)將R1,R2,R3及R4推入當前堆棧;/圖2(2)OSTCBCur-OSTCBStkPtr = SP;/SP入控制塊 /圖2(3)OSTCBCur = OSTCBHighRdy;/圖3(1)SP = OSTCBHighRdy -OS

54、TCBSTKPtr; /圖3(2)將R4,R3,R2及R1從新堆棧中彈(zhn dn)出;/圖3(3)執(zhí)行中斷返回指令;/圖3(4)84共一百三十八頁3.5 任務(rn wu)的創(chuàng)建uC/OS-II是通過任務控制(kngzh)塊來管理任務的;uC/OS-II有兩個用來創(chuàng)建任務的函數(shù):OSTaskCreate ( )、OSTaskCreateExt ( );OSTaskCreate ( )向下兼容,OSTaskCreateExt ( )是前一函數(shù)的擴展,提供了一些附加功能;任務可以在多任務調度開始前建立,也可以在其他任務執(zhí)行過程中建立;任務不能由中斷服務程序建立。85共一百三十八頁3.5.1 用

55、函數(shù)OSTaskCreate( )創(chuàng)建(chungjin)任務應用程序通過調用函數(shù)OSTaskCreate ()來創(chuàng)建一個任務,函數(shù)OSTaskCreate ( )源代碼如下: INT8U OSTaskCreate (void ( * task)(void * pd), / 指向任務的指針void * pdata, / 傳遞(chund)給任務的參數(shù)OS_STK *ptos, / 指向任務堆棧棧頂?shù)闹羔業(yè)NT8U prio / 任務的優(yōu)先級)86共一百三十八頁void *psp;INT8U err;if (prio OS_LOWEST_PRIO) /任務的優(yōu)先級必須在0到OS_LOWEST_P

56、RIO/之間檢測任務的優(yōu)先級是否合法 return (OS_PRIO_INVALID);OS_ENTER_CRITICAL();if (OSTCBPrioTblprio = (OS_TCB *)0) / 確認優(yōu)先級未被使用 OSTCBPrioTblprio = (OS_TCB *)1;/ 如果擬分配的優(yōu)先級是空閑的,通過/在OSTCBPrioTbl 中放置(fngzh)一個非空指針,保留該優(yōu)先級OS_EXIT_CRITICAL();psp = (void *)OSTaskStkInit(task ,pdata, ptos, 0); / 初始化任務堆棧,建立任務的堆棧,返回新的堆棧 /棧頂psp

57、,并保存在任務控制塊OS_TCB中,注意堆棧增長方向err = OSTCBInit( prio,psp, (void *)0, 0, 0,(void *)0, 0); / 獲得并初始化任務控制塊, 從空閑的OS_TCB池/中獲得并初始化一個任務控制塊OS_TCB87共一百三十八頁if (err = OS_NO_ERR) OS_ENTER_CRITICAL();OSTaskCtr+; / 從OS_TCBInit( )返回后,任務計數(shù)器加1,/用于跟蹤已經建立了的任務數(shù)目OS_EXIT_CRITICAL();if ( OSRunning) OSSched(); / 任務調度 /如果(rgu)OST

58、askCreate ()函數(shù)是在某個任務的執(zhí)行過程中被調用(OSRunning=1)/則任務調度函數(shù)會被調用來判斷是否新建立的任務比原來的任/務有更高的優(yōu)/先級。如果新任務的優(yōu)先級更高,內核會進行一次任務切換。else OS_ENTER_CRITICAL();OSTCBPrioTblprio = (OS_TCB *)0; / 放棄任務 /從OSTCBInit()返回后,要檢驗返回代碼,如果成功,就增加OSTaskCtr, /OSTaskCtr用于保存產生的任務數(shù)目。如果OSTCBInit()返回失敗,就置 /OSTCBPrioTblprio 的入口為0以放棄該任務的優(yōu)先級。OS_EXIT_CR

59、ITICAL();return (err); 88共一百三十八頁else OS_EXIT_CRITICAL();return (OS_PRIO_EXIST);89共一百三十八頁從函數(shù)OSTaskCreate( )的源代碼中可以看到,函數(shù)對待創(chuàng)建任務的優(yōu)先級別進行一系列判斷,確認該優(yōu)先級別合法且未被使用(shyng)之后,隨即調用函數(shù)OSTaskStkInit( )和OSTCBInit( )對任務堆棧和任務控制塊進行初始化。初始化成功后,除了把任務計數(shù)器加1外,還要進一步判斷uC/OS-II的核是否在運行狀態(tài)(即OSRunning的值是否為1),如果OSRunning的值為1,則調用OSSche

60、d( )進行任務調度。提問:能否調用OSTaskCreate( )函數(shù)來創(chuàng)建優(yōu)先級為OS_LOWEST_PRIO的任務?不能,因為優(yōu)先級OS_LOWEST_PRIO是為空閑任務保留的。如果這樣做,會返回代碼出錯信息OS_PRIO_EXIST。90共一百三十八頁3.5.2 用函數(shù)OSTaskCreateExt( )創(chuàng)建(chungjin)任務用OSTaskCreateExt( )函數(shù)來建立任務會更加靈活,但是會增加一些額外的開銷。函數(shù)OSTaskCreateExt ()源代碼如下:INT8U OSTaskCreateExt(void (*task)(void *pd), / 指向任務的指針voi

溫馨提示

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

最新文檔

評論

0/150

提交評論