![嵌入式-3(new)_第1頁](http://file3.renrendoc.com/fileroot_temp3/2021-12/29/79421ea0-30ba-407e-b365-3ec6eab9d788/79421ea0-30ba-407e-b365-3ec6eab9d7881.gif)
![嵌入式-3(new)_第2頁](http://file3.renrendoc.com/fileroot_temp3/2021-12/29/79421ea0-30ba-407e-b365-3ec6eab9d788/79421ea0-30ba-407e-b365-3ec6eab9d7882.gif)
![嵌入式-3(new)_第3頁](http://file3.renrendoc.com/fileroot_temp3/2021-12/29/79421ea0-30ba-407e-b365-3ec6eab9d788/79421ea0-30ba-407e-b365-3ec6eab9d7883.gif)
![嵌入式-3(new)_第4頁](http://file3.renrendoc.com/fileroot_temp3/2021-12/29/79421ea0-30ba-407e-b365-3ec6eab9d788/79421ea0-30ba-407e-b365-3ec6eab9d7884.gif)
![嵌入式-3(new)_第5頁](http://file3.renrendoc.com/fileroot_temp3/2021-12/29/79421ea0-30ba-407e-b365-3ec6eab9d788/79421ea0-30ba-407e-b365-3ec6eab9d7885.gif)
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、嵌入式操作系統(tǒng)嵌入式操作系統(tǒng)第三章第三章 C/OS-II中的任務(wù)中的任務(wù)2第第3章章 C/OS-II中的任務(wù)中的任務(wù)本部分的主要內(nèi)容包括: 任務(wù)的基本概念 任務(wù)代碼、任務(wù)控制塊和任務(wù)堆棧 任務(wù)的優(yōu)先權(quán) 任務(wù)就緒表結(jié)構(gòu)及其操作 任務(wù)切換及任務(wù)調(diào)度 任務(wù)的創(chuàng)建、刪除、掛起、恢復(fù)和查詢 C/OS-II的初始化和啟動33.1 3.1 任務(wù)的基本概念任務(wù)的基本概念3.1.1 任務(wù)及其內(nèi)存結(jié)構(gòu) 在設(shè)計一個較為復(fù)雜的應(yīng)用程序時,通常把一個大型任務(wù)分解成多個小任務(wù),然后在計算機(jī)中通過運行這些小任務(wù),最終達(dá)到完成大任務(wù)的目的。實時應(yīng)用程序的設(shè)計過程包括如何把問題分割成多個任務(wù)。每個任務(wù)都是整個應(yīng)用程序的一部分,
2、都被賦予一定的優(yōu)先級,有自己的一套CPU寄存器和??臻g。由于這種方法可以使系統(tǒng)并發(fā)地運行多個任務(wù),從而提高處理器的利用率,加快程序的執(zhí)行速度,因此現(xiàn)代操作系統(tǒng)幾乎都是多任務(wù)操作系統(tǒng)。 4 一個任務(wù),也稱作一個線程,是一個簡單的程序,與大任務(wù)分割成的小任務(wù)對應(yīng)的程序?qū)嶓w就叫做“任務(wù)”,而C/OS-II就是一個能對這些小任務(wù)的運行進(jìn)行管理和調(diào)度的多任務(wù)操作系統(tǒng)。 從代碼上看,C/OS-II的任務(wù)就是一個函數(shù)。而從任務(wù)的存儲結(jié)構(gòu)上看,C/OS-II的任務(wù)由三個部分組成:任務(wù)程序代碼(函數(shù))、任務(wù)堆棧和任務(wù)控制塊。其中任務(wù)控制塊就是關(guān)聯(lián)了任務(wù)代碼的程序控制塊(TCB),它記錄了任務(wù)的各個屬性;任務(wù)堆棧
3、則用來保存任務(wù)的工作環(huán)境;任務(wù)程序代碼就是任務(wù)的執(zhí)行部分。 5PC6 C/OS-II任務(wù)控制塊實質(zhì)上就是2.4.2節(jié)中所介紹的具有二級結(jié)構(gòu)的代碼控制塊,只不過用來指向代碼的指針是CPU程序指針(程序計數(shù)器)PC的副本。系統(tǒng)可以根據(jù)任務(wù)控制塊來了解代碼的相關(guān)信息,當(dāng)然也就是能夠找到代碼。 注:任務(wù)控制塊通過任務(wù)堆棧和任務(wù)代碼注:任務(wù)控制塊通過任務(wù)堆棧和任務(wù)代碼間接的關(guān)聯(lián)起來間接的關(guān)聯(lián)起來7 C/OS-II用任務(wù)控制塊鏈表對任務(wù)進(jìn)行管理,如下圖所示:8 C/OS-II的任務(wù)有兩種:用戶任務(wù)和系統(tǒng)任務(wù)。由應(yīng)用程序設(shè)計者編寫的任務(wù),叫做用戶任務(wù);由系統(tǒng)提供的任務(wù)叫做系統(tǒng)任務(wù)。用戶任務(wù)是為了解決應(yīng)用問題
4、而編寫的;系統(tǒng)任務(wù)是為應(yīng)用程序提供某種服務(wù)或為系統(tǒng)本身服務(wù)的。目前,在C/OS-II中,最多可以含有64個任務(wù)(包括用戶任務(wù)和系統(tǒng)任務(wù))。 9 C/OS II 支持64個任務(wù),每個任務(wù)有一個特定的優(yōu)先級。 任務(wù)的優(yōu)先級別用數(shù)字表示,0表示的任務(wù)的優(yōu)先級最高,數(shù)字越大表示的優(yōu)先級越低。 通過常數(shù)OS_LOWEST_PRIO (在OS_CFG.H中)定義系統(tǒng)的最低優(yōu)先級別,同時限定系統(tǒng)能容納的最多任務(wù)數(shù)量。 建議用戶不要使用優(yōu)先級為0、1、2、3、OS_LOWEST_PRIO-3、 OS_LOWEST_PRIO-2、 OS_LOWEST_PRIO-1、 OS_LOWEST_PRIO-0的任務(wù)。最低
5、的兩個已被目前版本的系統(tǒng)占用,將來版本可能會用到其它的。 103.1.2 任務(wù)的狀態(tài) C/OS-II是按照系統(tǒng)中只有一個CPU來設(shè)計的,在這種系統(tǒng)中,一個具體時刻只會有一個任務(wù)占用,及處在運行狀態(tài),而其他任務(wù)只能處在其他狀態(tài)。C/OS-II系統(tǒng)中的任務(wù)共有5種狀態(tài): 睡眠態(tài)(睡眠態(tài)(DORMANT):任務(wù)在沒有被配備任務(wù)控制塊或被剝奪了任務(wù)控制塊時的狀態(tài)叫作任務(wù)的睡眠態(tài)。 就緒態(tài)(就緒態(tài)(READY):如果系統(tǒng)為任務(wù)配備了任務(wù)控制塊且在任務(wù)就緒表中進(jìn)行了就緒登記,則任務(wù)就具備了運行的充分條件,這時的任務(wù)的狀態(tài)叫就緒態(tài)。11 運行態(tài)(運行態(tài)(RUNNING):):處于就緒態(tài)的任務(wù)如果經(jīng)調(diào)度器判斷
6、獲得了CPU的使用權(quán),則任務(wù)就進(jìn)入運行態(tài)。任何時刻只能有一個任務(wù)處于運行態(tài)。 等待態(tài)(等待態(tài)(WAITING):):正在運行的任務(wù),需要等待一段時間或需要等待一個事件發(fā)生再運行時,該任務(wù)就會把CPU的使用權(quán)讓給其他任務(wù)而使任務(wù)進(jìn)入waiting狀態(tài)。 注:進(jìn)入waiting的狀態(tài)有可能是因為延時,有可能是被掛起,有可能是等待的資源未獲得,總之,uC/OS將所有的已經(jīng)注冊了的但未就緒的任務(wù)歸為waiting態(tài)。 被中斷態(tài)(被中斷態(tài)(ISR):):正在運行的任務(wù)是可以被中斷的,除非該任務(wù)將中斷關(guān)了,或者uC/OS-將中斷關(guān)了。被中斷了的任務(wù)就進(jìn)入了中斷服務(wù)態(tài)(ISR)。 當(dāng)所有的任務(wù)都在等待事件發(fā)
7、生或等待延遲時間結(jié)束,uC/OS-執(zhí)行空閑任務(wù)(idle task),執(zhí)行OSTaskIdle() 函數(shù)。 12 在系統(tǒng)的管理下,一個任務(wù)可以在5個不同的狀態(tài)之間發(fā)生轉(zhuǎn)換。其轉(zhuǎn)換關(guān)系如圖所示 13 線上的函數(shù)作用:狀態(tài)遷移依靠這些函數(shù)完成143.1.3 用戶任務(wù)代碼的一般結(jié)構(gòu) 1. 用戶任務(wù)代碼的一般結(jié)構(gòu) 根據(jù)嵌入式系統(tǒng)任務(wù)的工作特點,任務(wù)的執(zhí)行代碼通常是一個無限循環(huán)結(jié)構(gòu)(對于一些一次性任務(wù)例外),并且在這個循環(huán)中可以響應(yīng)中斷,這種結(jié)構(gòu)也叫做超循環(huán)結(jié)構(gòu)。例3-1就是一個具有超循環(huán)結(jié)構(gòu)的任務(wù)的示意性代碼。 15 例3-1 一個用C語言編寫的任務(wù) void MyTask(void * pdata)
8、 for( ; ; )可以被中斷的用戶代碼;OS_ENTER_CRITICAL();/進(jìn)入臨界段(關(guān)中斷)不可以被中斷的用戶代碼;OS_EXIT_CRITICAL();/退出臨界段(開中斷)可以被中斷的用戶代碼; 從程序的角度來看,一個C/OS-II任務(wù)的代碼就是一個C語言函數(shù)。之所以把任務(wù)的參數(shù)定義成一個void類型的指針,是為了傳遞各種不同類型的數(shù)據(jù)。16 為了有效的對中斷進(jìn)行控制,在任務(wù)的代碼里可使用uC/OS-II定義的宏OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()來控制何時響應(yīng)中斷,何時屏蔽中斷。這兩個宏之間的代碼時是不會響應(yīng)中斷的,這種受保護(hù)的代碼段
9、叫臨界段。 代碼的臨界段也稱為臨界區(qū),指處理時不可分割的代碼。一旦這部分代碼開始執(zhí)行,則不允許任何中斷打入。為確保臨界段代碼的執(zhí)行不被中斷,在進(jìn)入臨界段之前必須關(guān)中斷,而臨界段代碼執(zhí)行完后,要立即開中斷。 17 2用戶應(yīng)用程序的一般結(jié)構(gòu) 從程序代碼來看,用戶任務(wù)就是一個C語言函數(shù),但這個函數(shù)不是自主函數(shù)main()調(diào)用的函數(shù),在系統(tǒng)中它與主函數(shù)main()處于平等的地位,它們何時被運行以及何時被終止是由操作系統(tǒng)來調(diào)度的。但要注意,main()畢竟是一個應(yīng)用程序的主函數(shù),是程序運行的入口點,所以雖然它不調(diào)用任務(wù),但要負(fù)責(zé)任務(wù)的創(chuàng)建并將它們交給系統(tǒng),至于何時運行它們,則與主函數(shù)無關(guān)。 18 用戶應(yīng)
10、用程序的代碼大體如下: 例3-2 用戶應(yīng)用程序的結(jié)構(gòu) void MyTask1(void * pdata)/定義用戶任務(wù)定義用戶任務(wù)1 for( ; ; ) void MyTask2(void * pdata)/定義用戶任務(wù)定義用戶任務(wù)2 for( ; ; ) 19void MyTask3(void * pdata)/定定義義用用戶戶任任務(wù)務(wù)3for( ; ; )void main()OSInit();/初始化初始化 C/OS-IIOSTaskCreate(MyTask1,);/創(chuàng)創(chuàng)建用建用戶戶任任務(wù)務(wù)1OSTaskCreate(MyTask2,);/創(chuàng)創(chuàng)建用建用戶戶任任務(wù)務(wù)2OSTaskCr
11、eate(MyTask3,);/創(chuàng)創(chuàng)建用建用戶戶任任務(wù)務(wù)3OSStart();/啟動啟動 C/OS-II20 其中,OSTaskCreate()是C/OS-II提供的用來創(chuàng)建任務(wù)的函數(shù);OSStart()啟動C/OS-II的函數(shù)。系統(tǒng)被啟動后,任務(wù)就由操作系統(tǒng)來管理和調(diào)度了。 213.1.4 系統(tǒng)任務(wù) 作為管理者,操作系統(tǒng)除了要管理用戶任務(wù)之外,可能會有一些內(nèi)部事務(wù)需要處理,最起碼要有一個沒有用戶任務(wù)可執(zhí)行時需要做的事情,因為計算機(jī)是不能停下來的。為了與用戶任務(wù)相區(qū)別,這種系統(tǒng)自己所需要的任務(wù)叫做系統(tǒng)任務(wù)。C/OS-II預(yù)定義了兩個系統(tǒng)任務(wù):空閑任務(wù)和統(tǒng)計任務(wù)。其中空閑任務(wù)是每個應(yīng)用程序必須使
12、用的,而統(tǒng)計任務(wù)則是應(yīng)用程序可以根據(jù)實際需要來選擇使用的。 22 1. 空閑任務(wù) C/OS-II總要建立一個空閑任務(wù)(idle task),這個任務(wù)在沒有其他任務(wù)進(jìn)入就緒狀態(tài)時投入運行。這個空閑任務(wù)OSTaskIdle()永遠(yuǎn)設(shè)為最低優(yōu)先級,即OS_LOWER_PRIO。空閑任務(wù)OSTaskIdle()的代碼如下: void OSTaskIdle( void * pdata) pdata = pdata; /防止某些編譯器報錯 for(;) OS_ENTER_CRITICAL(); /關(guān)閉中斷 OSIdleCtr+; /計數(shù) OS_EXIT_CRITICAL(); /開放中斷 C/OS-II規(guī)
13、定,一個用戶應(yīng)用程序必須使用這個空閑任務(wù),而且這個任務(wù)是不能用程序來刪除的。23 2統(tǒng)計任務(wù) C/OS-II提供的另一個系統(tǒng)任務(wù)就是統(tǒng)計任務(wù)OSTaskStat( ) OSTaskStat( )每秒運行1次,計算CPU利用率,即告訴用戶應(yīng)用程序使用了多少CPU時間,用百分比表示,精確度為1%。 如果將系統(tǒng)頭文件OS_CFG.H中的系統(tǒng)配置常數(shù)OS_TASK_STAT_EN設(shè)置為1,統(tǒng)計任務(wù)就會在操作系統(tǒng)初始化函數(shù)OSInit( )中調(diào)用OS_InitTaskStat()函數(shù)創(chuàng)建創(chuàng)建。24 在系統(tǒng)調(diào)用多任務(wù)啟動函數(shù)OSStart( )之前,用戶初始代碼中必須先建立至少一個用戶任務(wù)(如TaskSt
14、art),如果應(yīng)用程序打算使用統(tǒng)計任務(wù),需要在TaskStart任務(wù)中調(diào)用函數(shù) OSStatInit( )對統(tǒng)計任務(wù)進(jìn)行初始化初始化。之后再建立應(yīng)用程序中的其他任務(wù)。 應(yīng)該在用戶任務(wù)中(第一個任務(wù))啟動時鐘節(jié)拍。因為用戶不希望在多任務(wù)還沒有開始時就收到時鐘節(jié)拍中斷25void main (void)OSInit(); /初初 始化始化uC/OS-II /* 創(chuàng)建用戶起始任務(wù)創(chuàng)建用戶起始任務(wù)(以以TaskStart()作為起始任務(wù),也可以創(chuàng)建多個任務(wù)作為起始任務(wù),也可以創(chuàng)建多個任務(wù))*/OSStart(); /開開 始多任務(wù)調(diào)度始多任務(wù)調(diào)度void TaskStart (void *pdata)
15、/* 在這里安裝并啟動在這里安裝并啟動uC/OS-II的時鐘節(jié)拍的時鐘節(jié)拍 */OSStatInit(); / 初始化統(tǒng)計任務(wù)初始化統(tǒng)計任務(wù) /* 創(chuàng)建用戶應(yīng)用程序任務(wù)創(chuàng)建用戶應(yīng)用程序任務(wù) */for (;) /* 這里是這里是TaskStart()的代碼的代碼 */ OSTimeDly(10); /調(diào)用該函數(shù)的任務(wù)將自己延時調(diào)用該函數(shù)的任務(wù)將自己延時1010個時鐘并執(zhí)行一次任務(wù)調(diào)度個時鐘并執(zhí)行一次任務(wù)調(diào)度 263.1.5 任務(wù)的優(yōu)先權(quán)及優(yōu)先級別 uC/OS-II分為64個優(yōu)先級別,每一個級別都用一個數(shù)字表示。數(shù)字0的級別最高,數(shù)字越大優(yōu)先級別越低。 通常,一個應(yīng)用程序的任務(wù)數(shù)小于64,用戶可
16、根據(jù)應(yīng)用程序的需要,在OS_CFG.H中設(shè)置OS_LOWEST_PRIO,即定義了可供使用的優(yōu)先級別共OS_LOWEST_PRIO +1個。 固定地,系統(tǒng)總是把最低優(yōu)先級別自動賦給空閑任務(wù),如果系統(tǒng)中還有統(tǒng)計任務(wù),則其優(yōu)先級別為OS_LOWEST_PRIO -1。因此用戶任務(wù)可以使用的優(yōu)先級別是0,1,2,.,OS_LOWEST_PRIO-2,共OS_LOWEST_PRIO-1個 27 例:如果希望應(yīng)用程序中任務(wù)的優(yōu)先級別為28個,則表示最低優(yōu)先級別的常數(shù)OS_LOWEST_PRIO值應(yīng)該是多少?如果應(yīng)用程序中使用了系統(tǒng)提供的空閑任務(wù)和統(tǒng)計任務(wù),則該應(yīng)用程序最多可以安排多少個任務(wù)? 28 答:
17、表示最低優(yōu)先級別的常數(shù)OS_LOWEST_PRIO值應(yīng)該為27,優(yōu)先級別分別為0,1,2,3,.,27;由于系統(tǒng)空閑任務(wù)占用了優(yōu)先級別27,統(tǒng)計任務(wù)占用了優(yōu)先級別26,則應(yīng)用程序中最多可以安排優(yōu)先級別分別為0,1,2,.,25的26個任務(wù)。29 給某一個用戶任務(wù)的定義優(yōu)先級別,需要在調(diào)用系統(tǒng)函數(shù)OSTaskCreate()來創(chuàng)建任務(wù)時,用該函數(shù)的第4個參數(shù)prio來指定。 由于每個任務(wù)都具有惟一的優(yōu)先級別,因此C/OS-II通常也用任務(wù)的優(yōu)先級別來作為這個任務(wù)的標(biāo)識。 303.2 3.2 任務(wù)堆棧任務(wù)堆棧 任務(wù)堆棧是任務(wù)的重要組成部分。 所謂堆棧,就是在存儲器中按數(shù)據(jù)“后進(jìn)先出(LIFO)”的
18、原則組織的連續(xù)存儲空間。為了滿足任務(wù)切換和響應(yīng)中斷時保存CPU寄存器中的內(nèi)容及任務(wù)調(diào)用其他函數(shù)時的需要,每個任務(wù)都有自己的??臻g。所有C/OS-II任務(wù)的任務(wù)控制塊中都含有一個指向該任務(wù)堆棧的指針。31 C/OS-II中堆棧的數(shù)據(jù)類型為為OS_STK,在文件OS_CPU.H中定義: typedef unsigned int OS_STK; /該類型長度為該類型長度為16位位 這樣,在應(yīng)用程序中定義任務(wù)堆棧的棧區(qū)就非常簡單,即定義一個OS_STK類型的一個數(shù)組即可。例如:#define TASK_STK_SIZE 512 /定義堆棧的長度定義堆棧的長度(1024字節(jié)字節(jié))OS_STK TaskS
19、tkTASK_STK_SIZE; /定義一個數(shù)組來作為任務(wù)堆棧定義一個數(shù)組來作為任務(wù)堆棧 當(dāng)調(diào)用函數(shù)OSTaskCreate()來創(chuàng)建一個任務(wù)時,把數(shù)組的指針傳遞給函數(shù)OSTaskCreate()中的堆棧棧頂參數(shù)ptos,就可以把該數(shù)組與任務(wù)關(guān)聯(lián)起來而成為該任務(wù)的任務(wù)堆棧。 32 例3-4 創(chuàng)建任務(wù)函數(shù)OSTaskCreate()的原型如下: INT8U OSTaskCreate( void (*task)(void *pd), /指向任務(wù)的指針指向任務(wù)的指針 void *pdata, /傳遞給任務(wù)的參數(shù)傳遞給任務(wù)的參數(shù) OS_STK *ptos, /任務(wù)堆棧棧頂?shù)闹羔樔蝿?wù)堆棧棧頂?shù)闹羔?IN
20、T8U prio ); /指定任務(wù)優(yōu)先級別的參數(shù)指定任務(wù)優(yōu)先級別的參數(shù) ); 使用例3-1的代碼來作為任務(wù)代碼來創(chuàng)建一個任務(wù)MyTask,任務(wù)堆棧的長度為128字節(jié),優(yōu)先級別為20,任務(wù)參數(shù)pdata的實參為MyTaskAgu。試寫出main()函數(shù)的代碼。 33 #define MyTaskStkN 64 OS_STK MyTaskStkMyTaskStkN ; void main(void) OSTaskCreate( MyTask,/任務(wù)的指針任務(wù)的指針 &MyTaskAgu,/傳遞給任務(wù)的參數(shù)傳遞給任務(wù)的參數(shù) &MyTaskStkMyTaskStkN-1, /任務(wù)堆棧棧
21、頂?shù)刂啡蝿?wù)堆棧棧頂?shù)刂?20);/任務(wù)的優(yōu)先級別任務(wù)的優(yōu)先級別 34 堆棧的增長方向是隨系統(tǒng)所使用的處理器不同而不同。因此在使用函數(shù)OSTaskCreate() 創(chuàng)建任務(wù)時,一定要注意所使用的處理器對堆棧增長方向的支持是向上的還是向下的。 35 上一練習(xí)時假設(shè)使用了支持堆棧向下增長方式的處理器設(shè)置參數(shù)ptos。如果使用的處理器支持堆棧的增長方向向上,則應(yīng)該為: OSTaskCreate( MyTask, &MytaskAgu, &MyTaskStk0, 20); 為了提高應(yīng)用程序的移植性,在編寫代碼時可兼顧兩種情況,利用OS_CFG.H文件中的常數(shù)OS_STK_GROWTH 作
22、為選擇開關(guān),使用戶可通過定義該常數(shù)的值來選擇相應(yīng)代碼段,以適應(yīng)不同的堆棧增長方向的需要。試改寫上一練習(xí)代碼。36#define MyTaskStkN 64OS_STK MyTaskStkMyTaskStkN ;void main(void) # if OS_STK_GROWTH=1 OSTaskCreate( MyTask, /任務(wù)的指針任務(wù)的指針 &MyTaskAgu, /傳遞給任務(wù)的參數(shù)傳遞給任務(wù)的參數(shù) &MyTaskStkMyTaskStkN-1, /任務(wù)堆棧棧頂?shù)刂啡蝿?wù)堆棧棧頂?shù)刂?20); /任務(wù)的優(yōu)先級別任務(wù)的優(yōu)先級別#else OSTaskCreate( MyTa
23、sk, /任務(wù)的指針任務(wù)的指針 &MyTaskAgu, /傳遞給任務(wù)的參數(shù)傳遞給任務(wù)的參數(shù) &MyTaskStk0, /任務(wù)堆棧棧頂?shù)刂啡蝿?wù)堆棧棧頂?shù)刂?20); /任務(wù)的優(yōu)先級別任務(wù)的優(yōu)先級別#endif 373.2.2 任務(wù)堆棧的初始化 當(dāng)CPU啟動運行一個任務(wù)時,CPU的各寄存器總是需要預(yù)置一些初始數(shù)據(jù),例如指向任務(wù)的指針、任務(wù)堆棧指針、程序狀態(tài)字等。那么,系統(tǒng)啟動任務(wù)時,CPU從何處可以獲得這些數(shù)據(jù)呢?最方便的方法就是讓CPU從這個任務(wù)的任務(wù)堆棧里獲得這些數(shù)據(jù)。 C/OS-II在創(chuàng)建任務(wù)函數(shù)OSTaskCreat ()中通過調(diào)用任務(wù)堆棧初始化函數(shù)OSTaskStkIni
24、t ()來完成任務(wù)堆棧初始化工作的,其原型如下: 38 OS_STK * OSTaskStkInit ( void ( * task)(void * pd), void * pdata, OS_STK * ptos, INIT16U opt ); 通常用戶不會直接接觸到這個函數(shù),該函數(shù)由C/OS-II所提供的任務(wù)創(chuàng)建函數(shù)OSTaskCreate()來調(diào)用。 由于各處理器的寄存器及對堆棧的操作方式不同,因此該函數(shù)需要用戶在進(jìn)行C/OS-II的移植時,按所使用的處理器由用戶來編寫。 393.3任務(wù)控制塊(TCB)及任務(wù)控制塊鏈表 C/OS-II用來記錄任務(wù)的堆棧指針、任務(wù)的當(dāng)前狀態(tài)、任務(wù)的優(yōu)先級別
25、等一些與任務(wù)管理有關(guān)的屬性的表就叫做任務(wù)控制塊。 C/OS-II把系統(tǒng)所有任務(wù)的控制塊鏈接為兩條鏈表,并通過它們管理各個任務(wù)。40 一旦任務(wù)建立,一個任務(wù)控制塊OS_TCB就被賦值。 任務(wù)控制塊是一個數(shù)據(jù)結(jié)構(gòu),保存該任務(wù)的相關(guān)參數(shù),包括任務(wù)堆棧指針,任務(wù)的當(dāng)前狀態(tài),任務(wù)的優(yōu)先級等。 任務(wù)CPU使用權(quán)被剝奪時,TCB保存該時刻任務(wù)狀態(tài);任務(wù)重新得到CPU控制權(quán)時,TCB確保任務(wù)從當(dāng)時被中斷的那一點絲毫不差地繼續(xù)執(zhí)行。 OS_TCB全部駐留在RAM中。 任務(wù)控制塊就相當(dāng)于一個任務(wù)的身份證,沒有任務(wù)控制塊的任務(wù)是不能被系統(tǒng)承認(rèn)和管理的。3.3.1 任務(wù)控制塊的結(jié)構(gòu)41 任務(wù)控制塊的結(jié)構(gòu)的定義如 p5
26、2所示 任務(wù)控制塊結(jié)構(gòu)的主要成員(需要熟知): typedef struct os_tcb OS_STK *OSTCBStkPtr; /指向任務(wù)堆棧棧頂?shù)闹羔樦赶蛉蝿?wù)堆棧棧頂?shù)闹羔?struct os_tcb *OSTCBNext; /指向后一個任務(wù)控制塊的指針指向后一個任務(wù)控制塊的指針 struct os_tcb *OSTCBPrev; /指向前一個任務(wù)控制塊的指針指向前一個任務(wù)控制塊的指針 INT16U OSTCBDly; /任務(wù)等待的時限(節(jié)拍數(shù))任務(wù)等待的時限(節(jié)拍數(shù)) 當(dāng)需要把任務(wù)延時若干時鐘節(jié)拍時,或者需要把任務(wù)掛起一段時間當(dāng)需要把任務(wù)延時若干時鐘節(jié)拍時,或者需要把任務(wù)掛起一段時間
27、以等待某事件的發(fā)生時需要用到這個變量。如果這個變量為以等待某事件的發(fā)生時需要用到這個變量。如果這個變量為0,表示,表示任務(wù)不延時,或者表示等待事件發(fā)生的時間沒有限制任務(wù)不延時,或者表示等待事件發(fā)生的時間沒有限制 。 INT8U OSTCBStat; /任務(wù)的當(dāng)前狀態(tài)標(biāo)志任務(wù)的當(dāng)前狀態(tài)標(biāo)志 INT8U OSTCBPrio; /任務(wù)的優(yōu)先級別任務(wù)的優(yōu)先級別 OS_TCB;42 其中OSTCBStat:任務(wù)狀態(tài)字,可取下列值: OS_STAT_RDY: 處于就緒狀態(tài) OS_STAT_SEM: 處于等待信號量狀態(tài) OS_STAT_MBOX:處于等待郵箱狀態(tài) OS_STAT_Q: 處于等待消息隊列狀態(tài)
28、OS_STAT_SUSPEND:處于被掛起狀態(tài) OS_STAT_MUTEX:處于等待互斥信號量狀態(tài)433.3.2 任務(wù)控制塊鏈表兩條鏈表來管理任務(wù)控制塊: 空任務(wù)塊鏈表(所有任務(wù)控制塊還沒有分配給任務(wù)),是在應(yīng)用程序調(diào)用函數(shù)OSInit( )對系統(tǒng)進(jìn)行初始化時建立的。 任務(wù)塊鏈表(所有任務(wù)控制塊已經(jīng)分配給任務(wù)),是在調(diào)用函數(shù)OSTaskCreate( )創(chuàng)建任務(wù)時建立的。建立任務(wù)控制塊鏈表的具體做法是,從空鏈表摘取一個空任務(wù)控制塊,然后填充上任務(wù)屬性后再形成新的鏈表。44 系統(tǒng)在調(diào)用函數(shù)OSInit()對C/OS-II系統(tǒng)進(jìn)行初始化時,先在RAM中建立一個OS_TCB結(jié)構(gòu)類型的數(shù)組OSTCBT
29、bl ,每個數(shù)組元素就是一個任務(wù)控制塊,然后把這些控制塊鏈接成一個如圖所示的鏈表。由于鏈表中的這些控制塊還沒有與具體任務(wù)相關(guān)聯(lián),因此這個鏈表叫做空任務(wù)塊鏈表OSTCBFreeList。45 每當(dāng)應(yīng)用程序調(diào)用系統(tǒng)函數(shù)OSTaskCreate()創(chuàng)建一個任務(wù)時,系統(tǒng)就會將任務(wù)控制塊鏈表頭指針OSTCBFreeList指向的任務(wù)控制塊分配給該任務(wù)。在給任務(wù)控制塊中的各成員賦值后,就按任務(wù)控制塊鏈表的頭指針OSTCBList將其加入到任務(wù)控制塊鏈表中。 下圖是在上圖空任務(wù)控制塊鏈表基礎(chǔ)上,應(yīng)用程序創(chuàng)建了兩個用戶任務(wù)并使用了兩個系統(tǒng)任務(wù)(空閑任務(wù)和統(tǒng)計任務(wù))的情況時,空任務(wù)塊鏈表和任務(wù)塊鏈表的結(jié)構(gòu)示意圖
30、(圖中陰影區(qū)域為任務(wù)塊鏈表)。 46473.3.3 任務(wù)控制塊初始化 當(dāng)用戶程序調(diào)用函數(shù)OSTaskCreate() 創(chuàng)建一個任務(wù)時,這個函數(shù)會調(diào)用系統(tǒng)函數(shù)OSTCBInit() 來為任務(wù)控制塊進(jìn)行初始化。任務(wù)控制塊初始化函數(shù)OSTCBInit()做三件事:1、從空任務(wù)控制塊鏈表中獲取一個任務(wù)控制塊;2、用任務(wù)的屬性值對任務(wù)控制塊各個成員進(jìn)行賦值;3、把這個任務(wù)控制塊鏈入到任務(wù)控制塊使用鏈表的頭部。48 初始化任務(wù)控制塊函數(shù)OSTCBInit() 的原型如下:INT8U OSTCBInit(INT8U Prio,/任務(wù)的優(yōu)先級別,保存在任務(wù)的優(yōu)先級別,保存在OSTCBPrio中中OS_STK
31、*ptos, /任務(wù)堆棧棧頂指針,保存在任務(wù)堆棧棧頂指針,保存在OSTCBStkPtr中中OS_STK *pbos, /任務(wù)堆棧棧底指針,保存在任務(wù)堆棧棧底指針,保存在OSTCBStkBottom中中INT16U id, /任務(wù)的標(biāo)示符,保存在任務(wù)的標(biāo)示符,保存在OSTCBId中中INT16U stk_size, /任務(wù)堆棧的長度,保存在任務(wù)堆棧的長度,保存在OSTCBStkSize中中void *pext, /任務(wù)控制塊的擴(kuò)展指針,保存在任務(wù)控制塊的擴(kuò)展指針,保存在OSTCBExtPtr中中INT16U opt /任務(wù)的控制塊的選擇項,保存在任務(wù)的控制塊的選擇項,保存在OSTCBOpt中中)
32、;493.4 任務(wù)就緒表及任務(wù)調(diào)度 多任務(wù)操作系統(tǒng)的核心:任務(wù)調(diào)度。 調(diào)度定義:就是通過一個算法在多個任務(wù)中確定哪個任務(wù)來運行。做這項工作的就是調(diào)度器。 任務(wù)調(diào)度的思想:總是讓優(yōu)先級最高的就緒任務(wù)處于運行狀態(tài)。 C/OS-II進(jìn)行任務(wù)調(diào)度的依據(jù):任務(wù)就續(xù)表。50 至于什么是任務(wù)就緒表?可以這樣理解,為了能使系統(tǒng)清楚地知道系統(tǒng)中哪些任務(wù)已經(jīng)就緒,哪些還沒有就緒, C/OS-II在RAM中設(shè)立了一個記錄表,系統(tǒng)中的每個任務(wù)都在這個表占據(jù)一個位置,并用這個位置的狀態(tài)( 1或者0)來表示任務(wù)是否處于就緒狀態(tài)。這個表就叫做任務(wù)就緒表。 513.4.1 任務(wù)就緒表結(jié)構(gòu) 每個就緒的任務(wù)都放入就緒表中(rea
33、dy list)中,就緒表用兩個變量表示:OSRdyGrp、OSRdyTbl 。在OSRdyGrp中,任務(wù)按優(yōu)先級分組,8個任務(wù)為一組。OSRdyGrp中的每一位表示8組任務(wù)中每一組是否有進(jìn)入就緒態(tài)的任務(wù)。任務(wù)進(jìn)入就緒態(tài)時,就緒表OSRdyTbl 中的相應(yīng)元素的相應(yīng)位也置為1。OSRdyGrp和OSRdyTbl 之間的關(guān)系見下圖,它們之間的關(guān)系是按照以下規(guī)則給出的:當(dāng)當(dāng)OSRdyTbl0中的任何一位是中的任何一位是1時,時,OSRdyGrp的第的第0位置位置1;當(dāng)當(dāng)OSRdyTbl1中的任何一位是中的任何一位是1時,時,OSRdyGrp的第的第1位置位置1;當(dāng)當(dāng)OSRdyTbl2中的任何一位是
34、中的任何一位是1時,時,OSRdyGrp的第的第2位置位置1;當(dāng)當(dāng)OSRdyTbl3中的任何一位是中的任何一位是1時,時,OSRdyGrp的第的第3位置位置1;5253 就緒表OSRdyTbl 數(shù)組的大小取決于OS_LOWEST_PR1O(見文件OS_CFG.H)。當(dāng)用戶的應(yīng)用程序中任務(wù)數(shù)目比較少時,減少OS_LOWEST_PR1O 的值可以降低C/OS-對RAM(數(shù)據(jù)空間)的需求量。 那么如何根據(jù)任務(wù)的優(yōu)先級別查找任務(wù)在就緒表的位置呢? 從圖中可以看出,由于優(yōu)先級別是一個單字節(jié)的數(shù)字,而且最大值不會超過63,即二進(jìn)制00111111,因此,可以把優(yōu)先級別看成是一個6位的二進(jìn)制數(shù),這樣就可以用
35、高3位(Y、Y、Y)來指明變量OSRdyGrp的具體數(shù)據(jù)位,并用來確定就緒表數(shù)組元素的下標(biāo);用低3位(X、X、X)來指明該數(shù)組元素的具體數(shù)據(jù)位。 54 例3-5:已知某一個已經(jīng)就緒的任務(wù)優(yōu)先級別為prio=30,試判斷應(yīng)該在就緒表的哪一位置上置1。 答:30的二進(jìn)制形式為00011110,其低6位為011110,于是可知應(yīng)該把變量OSRdyGrp的D3位置1 , 同時要在OSRdyTbl3 的D6位上置1 。55 根據(jù)就緒表確定最高優(yōu)先級兩個關(guān)鍵:n優(yōu)先級數(shù)分解為高三位和低三位分別確定;n高優(yōu)先級有著小的優(yōu)先級號 。563.4.2 對任務(wù)就緒表的操作 系統(tǒng)對于就緒表主要有三個操作:登記、注銷和
36、從就緒表的就緒任務(wù)中得知具有最高優(yōu)先級任務(wù)的標(biāo)識(優(yōu)先級prio)。 57 1. 登記 登記:指的是當(dāng)某個任務(wù)處于就緒狀態(tài)時,系統(tǒng)將該任務(wù)登記在任務(wù)就緒表中,即在就續(xù)表中將該任務(wù)的對應(yīng)位置1。 在程序中,可用類似于下面的代碼把優(yōu)先級為prio的任務(wù)置為就緒態(tài):OSRdyGrp | = OSMapTblprio3;OSRdyTblprio3 | = OSMapTblprio & 0 x07; 其中,OSMapTbl 是C/OS-II為加快運算速度定義的一個數(shù)組,各元素為:OSMapTbl0 = 0000 0001BOSMapTbl1 = 0000 0010BOSMapTbl2 = 000
37、0 0100BOSMapTbl3 = 0000 1000BOSMapTbl4 = 0001 0000BOSMapTbl5 = 0010 0000BOSMapTbl6 = 0100 0000BOSMapTbl7 = 1000 0000B58 例1:使優(yōu)先級為12的任務(wù)進(jìn)入就緒狀態(tài),12=1100b, OSRdyGrp|= OSMapTblprio 3 |= OSMapTbl1 |= 00000010OSRdyTblprio 3|= OSMapTblprio & 0 x07 |= OSMapTbl100b |= OSMapTbl4 |= 00010000即OSRdyGrp的第1位置1,OS
38、RdyTbl1的第4位置15960 例2:使優(yōu)先級為21的任務(wù)進(jìn)入就緒態(tài),21=10 101b,OSRdyGrp|= OSMapTblprio 3 |= OSMapTbl10b= OSMapTbl2 |= 00000100OSRdyTblprio 3|= OSMapTblprio & 0 x07 |= OSMapTbl101b |= OSMapTbl5 |= 00100000即OSRdyGrp的第2位置1,OSRdyTbl2的第5位置16162 2. 注銷 注銷:指的是當(dāng)某個任務(wù)需要脫離就緒狀態(tài)時,系統(tǒng)在就緒表中將該任務(wù)的對應(yīng)位置0。 如果要使一個優(yōu)先級別為prio的任務(wù)脫離就緒狀態(tài),
39、則可使用如下代碼:If(OSRdyTblprio3&= OSMapTblprio & 0 x07)=0)OSRdyGrp&= OSMapTblprio3; 脫離就緒態(tài):將任務(wù)就緒表OSRdyTblprio3相應(yīng)元素的相應(yīng)位清零,而且當(dāng)OSRdyTblprio3中的所有位都為零時,即全組任務(wù)中沒有一個進(jìn)入就緒態(tài)時,OSRdyGrp的相應(yīng)位才為零。 63 例:使優(yōu)先級為12的任務(wù)脫離就緒表 答: 欲使優(yōu)先級為12的任務(wù)進(jìn)入就緒態(tài) 優(yōu)先級為12,即00001100BOSRdyGrp | = OSMapTblprio 3 ; (OSMapTbl1 = 0000 0010)OSR
40、dyTbl1 | = OSMapTblprio &0 x07 ; (OSMapTbl4 = 0001 0000) 欲使優(yōu)先級為12的任務(wù)脫離就緒態(tài) OSMapTblprio & 0 x07 = OSMapTbl4 = 11101111 OSMapTblprio 3 = OSMapTbl1 = 11111101如果OSRdyTblprio 3 &= OSMapTblprio & 0 x07 = 0 (該行所有任務(wù)都是非就緒態(tài))則OSRdyGrp = OSRdyGrp & OSMapTblprio 3 = 064065 3找出進(jìn)入就緒態(tài)的優(yōu)先級最高的任務(wù) 從
41、任務(wù)就緒表中獲取優(yōu)先級別最高的就緒任務(wù)可用如下代碼:y = OSUnMapTblOSRdyGrp;/獲得優(yōu)先級別的獲得優(yōu)先級別的D5、D4、D3位位x = OSUnMapTblOSRdyTbly;/獲得優(yōu)先級別的獲得優(yōu)先級別的D2、D1、D0位位Prio =(y3)+x;/獲得就緒任務(wù)的優(yōu)先級別獲得就緒任務(wù)的優(yōu)先級別 或y = OSUnMapTblOSRdyGrp;Prio = (INT8U)(y3)+OSUnMapTblOSRdyTbly);66 該代碼執(zhí)行后,得到的是最高優(yōu)先級就緒任務(wù)的優(yōu)先級別。其中,OSUnMapTbl同樣是C/OS-II為加快運算速度定義的一個數(shù)組,共有256個元素,
42、其定義如下: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, 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
43、, 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, 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
44、 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, 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
45、, 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; 67 例:已知OSRdyGrp=01101000b, OSRdyTbl3=11100100b,找出進(jìn)入就緒態(tài)的優(yōu)先級最高的任務(wù) OSRdyGrp=01101000b=0 x68,查OSUnMapTbl0 x68得到的值是3,y=3。 OSRdyTbl3=11100100b=0 xE4,則O
46、SUnMapTbl0 xE4的值是2,x=2。 Prio= (y 3) + x=3*8+2=26。6869 例2 已知OSRdyGrp=00100100b, OSRdyTbl2=00010010b,找出進(jìn)入就緒態(tài)的優(yōu)先級最高的任務(wù)y=OSUnMapTblOSRdyGrp=OSUnMapTbl100100b =OSUnMapTbl0 x24=2x = OSUnMapTblOSRdyTbly= OSUnMapTblOSRdyTbl2 =OSUnMapTbl00010010b =OSUnMapTbl0 x12=1prio = (y 3) + x =(23)+1=17 70713.4.3 任務(wù)的調(diào)度1
47、. 調(diào)度器的主要工作 任務(wù)切換:在多任務(wù)系統(tǒng)中,令CPU中止當(dāng)前正在運行的任務(wù)而去運行另一個任務(wù)的工作。 任務(wù)調(diào)度:按某種規(guī)則進(jìn)行任務(wù)切換的工作。 調(diào)度的發(fā)生條件:系統(tǒng)或用戶任務(wù)調(diào)用系統(tǒng)函數(shù)或者執(zhí)行中斷服務(wù)程序結(jié)束時。 任務(wù)調(diào)度由任務(wù)調(diào)度器完成,調(diào)度器主要工作:1)在任務(wù)就緒表中查找具有最高優(yōu)先級別的就緒任務(wù)。2)實現(xiàn)任務(wù)切換。 C/OS-II有兩種調(diào)度器:任務(wù)級調(diào)度器(由OSSched() 實現(xiàn))、中斷級調(diào)度器(由OSIntExt ()實現(xiàn))。 任務(wù)切換的兩個步驟:1)獲得待運行任務(wù)的TCB指針。2)進(jìn)行斷點數(shù)據(jù)的切換。 72 2. 獲得待運行任務(wù)的TCB指針 由于操作系統(tǒng)是通過任務(wù)的任務(wù)控
48、制塊TCB來管理任務(wù)的,因此調(diào)度器真正實施任務(wù)切換之前的主要工作就是要獲得待運行任務(wù)的任務(wù)控制塊指針和當(dāng)前任務(wù)的任務(wù)控制塊指針。 任務(wù)級的調(diào)度函數(shù)OSSched( )代碼如下 :void OSSched (void)INT8U y;OS_ENTER_CRITICAL(); /關(guān)中斷if (OSLockNesting | OSIntNesting) = 0) /如果調(diào)用來自中斷服務(wù)程序,或者至少調(diào)用了一次給任務(wù)調(diào)度上鎖函數(shù),任務(wù)調(diào)度函數(shù)將退出 73y = OSUnMapTblOSRdyGrp;OSPrioHighRdy = (INT8U)(y 0。 75 2)首先從任務(wù)就緒表中查得的最高優(yōu)先級別
49、就緒任務(wù)的優(yōu)先級別OSPrioHighRdy;然后在確認(rèn)了這個就緒任務(wù)不是當(dāng)前正在運行的任務(wù)(OSPrioCur是存放正在運行任務(wù)的優(yōu)先級別的變量)的條件下,用OSPrioHighRdy作為下標(biāo)去訪問數(shù)組OSTCBPrioTbl,把數(shù)組元素OSTCBPrioTblOSPrioHighRdy的值(即待運行就緒任務(wù)的任務(wù)控制塊指針)付給指針變量OSTCBHighRdy。于是可以依據(jù)OSTCBHighRdy和OSTCBCur這兩個分別指向待運行任務(wù)控制塊和當(dāng)前任務(wù)控制塊的指針在宏OS_TASK_SW( )中實施任務(wù)切換了。 763. 任務(wù)切換OS_TASK_SW( )任務(wù)級的任務(wù)切換需完成以下2步操
50、作: 將被掛起任務(wù)的處理器寄存器推入堆棧 將較高優(yōu)先級任務(wù)的寄存器值從堆棧中恢復(fù)到寄存器中 任務(wù)級的任務(wù)切換由OS_TASK_SW( )宏完成. #define OS_TASK_SW( ) OSCtxSw( )77 下圖1示意C/OS-II在調(diào)用OS_TASK_SW( )之前一些變量和數(shù)據(jù)結(jié)構(gòu)的狀況。為了便于討論,構(gòu)造了一個假想的CPU,該CPU有8個寄存器:1個堆棧指針(SP);1個程序計數(shù)器(PC);1個處理器狀態(tài)寄存器(PSW);4個通用寄存器(R1,R2,R3及R4)。 78(1)(3)(2)(5)(4)79 下圖2示意調(diào)用OS_TASK_SW( )以及保存被掛起任務(wù)的CPU寄存器之后
51、,一些變量和數(shù)據(jù)結(jié)構(gòu)的狀況:保存當(dāng)前任務(wù)CPU寄存器的值 80(1) 調(diào)用含有中斷指令的函數(shù)OS_TASK_SW( ),強(qiáng)制處理器保存PSW和PC的當(dāng)前值(2) 軟中斷的執(zhí)行從保存通用寄存器開始,順序是R1,R2,R3,R4(3) 然后堆棧指針寄存器被保存在當(dāng)前任務(wù)的OS_TCB中。此時,CPU的SP寄存器和OSTCBCurOSTCBStkPtr都指向當(dāng)前任務(wù)堆棧的同一位置81 下圖3示意執(zhí)行任務(wù)切換最后一段代碼之后變量和數(shù)據(jù)結(jié)構(gòu)的狀況:重新裝入要運行的任務(wù)82(1) 由于新的當(dāng)前任務(wù)是將要重新開始運行的任務(wù),任務(wù)切換代碼將OSTCBHighRdy復(fù)制到OSTCBCur(2) 從OS_TCB中
52、找出將要重新開始運行的任務(wù)的堆棧指針(在OSTCBHighRdyOSTCBStkPtr中),裝入CPU的SP寄存器中。此時,SP寄存器指向堆棧中存有寄存器R4值的位置(3) 按相反的方向從堆棧中彈出通用寄存器(4) 通過執(zhí)行中斷返回指令,PC和PSW的值裝回到CPU中。此時,由于程序計數(shù)器PC的值變了,重新開始運行的任務(wù)代碼從PC指向的那一點開始運行,于是切換到新任務(wù)代碼的過程完成了。8384 任務(wù)切換OS_TASK_SW()的代碼void OSCtxSw(void)將R1,R2,R3及R4推入當(dāng)前堆棧;/圖2(2)OSTCBCur-OSTCBStkPtr = SP;/SP入控制塊 /圖2(3
53、)OSTCBCur = OSTCBHighRdy;/圖3(1)SP = OSTCBHighRdy -OSTCBSTKPtr; /圖3(2)將R4,R3,R2及R1從新堆棧中彈出;/圖3(3)執(zhí)行中斷返回指令;/圖3(4)853.5 任務(wù)的創(chuàng)建 uC/OS-II是通過任務(wù)控制塊來管理任務(wù)的; uC/OS-II有兩個用來創(chuàng)建任務(wù)的函數(shù):OSTaskCreate ( )、OSTaskCreateExt ( ); OSTaskCreate ( )向下兼容,OSTaskCreateExt ( )是前一函數(shù)的擴(kuò)展,提供了一些附加功能; 任務(wù)可以在多任務(wù)調(diào)度開始前建立,也可以在其他任務(wù)執(zhí)行過程中建立; 任務(wù)
54、不能由中斷服務(wù)程序建立。863.5.1 用函數(shù)OSTaskCreate( )創(chuàng)建任務(wù) 應(yīng)用程序通過調(diào)用函數(shù)OSTaskCreate ()來創(chuàng)建一個任務(wù),函數(shù)OSTaskCreate ( )源代碼如下: INT8U OSTaskCreate (void ( * task)(void * pd), / 指向任務(wù)的指針void * pdata, / 傳遞給任務(wù)的參數(shù)OS_STK *ptos, / 指向任務(wù)堆棧棧頂?shù)闹羔業(yè)NT8U prio / 任務(wù)的優(yōu)先級)87void *psp;INT8U err;if (prio OS_LOWEST_PRIO) /任務(wù)的優(yōu)先級必須在0到OS_LOWEST_PRI
55、O/之間檢測任務(wù)的優(yōu)先級是否合法 return (OS_PRIO_INVALID);OS_ENTER_CRITICAL();if (OSTCBPrioTblprio = (OS_TCB *)0) / 確認(rèn)優(yōu)先級未被使用 OSTCBPrioTblprio = (OS_TCB *)1; / 如果擬分配的優(yōu)先級是空閑的,通過/在OSTCBPrioTbl 中放置一個非空指針,保留該優(yōu)先級OS_EXIT_CRITICAL();psp = (void *)OSTaskStkInit(task ,pdata, ptos, 0); / 初始化任務(wù)堆棧,建立任務(wù)的堆棧,返回新的堆棧 /棧頂psp,并保存在任務(wù)控
56、制塊OS_TCB中,注意堆棧增長方向err = OSTCBInit( prio,psp, (void *)0, 0, 0,(void *)0, 0); / 獲得并初始化任務(wù)控制塊, 從空閑的OS_TCB池/中獲得并初始化一個任務(wù)控制塊OS_TCB88if (err = OS_NO_ERR) OS_ENTER_CRITICAL();OSTaskCtr+; / 從OS_TCBInit( )返回后,任務(wù)計數(shù)器加1,/用于跟蹤已經(jīng)建立了的任務(wù)數(shù)目OS_EXIT_CRITICAL();if ( OSRunning) OSSched(); / 任務(wù)調(diào)度 /如果OSTaskCreate ()函數(shù)是在某個任務(wù)
57、的執(zhí)行過程中被調(diào)用(OSRunning=1)/則任務(wù)調(diào)度函數(shù)會被調(diào)用來判斷是否新建立的任務(wù)比原來的任/務(wù)有更高的優(yōu)/先級。如果新任務(wù)的優(yōu)先級更高,內(nèi)核會進(jìn)行一次任務(wù)切換。else OS_ENTER_CRITICAL();OSTCBPrioTblprio = (OS_TCB *)0; / 放棄任務(wù) /從OSTCBInit()返回后,要檢驗返回代碼,如果成功,就增加OSTaskCtr, /OSTaskCtr用于保存產(chǎn)生的任務(wù)數(shù)目。如果OSTCBInit()返回失敗,就置 /OSTCBPrioTblprio 的入口為0以放棄該任務(wù)的優(yōu)先級。OS_EXIT_CRITICAL();return (err
58、); 89else OS_EXIT_CRITICAL();return (OS_PRIO_EXIST);90 從函數(shù)OSTaskCreate( )的源代碼中可以看到,函數(shù)對待創(chuàng)建任務(wù)的優(yōu)先級別進(jìn)行一系列判斷,確認(rèn)該優(yōu)先級別合法且未被使用之后,隨即調(diào)用函數(shù)OSTaskStkInit( )和OSTCBInit( )對任務(wù)堆棧和任務(wù)控制塊進(jìn)行初始化。初始化成功后,除了把任務(wù)計數(shù)器加1外,還要進(jìn)一步判斷uC/OS-II的核是否在運行狀態(tài)(即OSRunning的值是否為1),如果OSRunning的值為1,則調(diào)用OSSched( )進(jìn)行任務(wù)調(diào)度。 提問:能否調(diào)用OSTaskCreate( )函數(shù)來創(chuàng)建優(yōu)
59、先級為OS_LOWEST_PRIO的任務(wù)?不能,因為優(yōu)先級OS_LOWEST_PRIO是為空閑任務(wù)保留的。如果這樣做,會返回代碼出錯信息OS_PRIO_EXIST。913.5.2 用函數(shù)OSTaskCreateExt( )創(chuàng)建任務(wù) 用OSTaskCreateExt( )函數(shù)來建立任務(wù)會更加靈活,但是會增加一些額外的開銷。函數(shù)OSTaskCreateExt ()源代碼如下:INT8U OSTaskCreateExt(void (*task)(void *pd), / 指向任務(wù)的指針void *pdata,/ 傳遞給任務(wù)的參數(shù)OS_STK *ptos, / 指向任務(wù)堆棧棧頂?shù)闹羔業(yè)NT8U pri
60、o, / 任務(wù)的優(yōu)先級INT16U id, / 任務(wù)的標(biāo)示OS_STK *pbos, / 任務(wù)堆棧棧底的指針I(yè)NT32U stk_size, / 任務(wù)堆棧的容量void *pext, / 指向附加數(shù)據(jù)域的指針I(yè)NT16U opt / 用于設(shè)置操作選項); 923.5.3 創(chuàng)建任務(wù)的一般方法 可在調(diào)用函數(shù)OSStart( )啟動任務(wù)調(diào)度之前來創(chuàng)建。 在任務(wù)中來創(chuàng)建。 uC/OS-II的規(guī)定:在OSStart( )啟動任務(wù)調(diào)度之前必須創(chuàng)建至少一個用戶任務(wù)。這樣,在OSStart ( )之前先創(chuàng)建一個任務(wù),并賦予它最高的優(yōu)先級,從而使它成為起始任務(wù),然后在這個起始任務(wù)中,再創(chuàng)建其它各任務(wù)。如果要使用系統(tǒng)提供的統(tǒng)計任務(wù),則統(tǒng)計任務(wù)的初始化函數(shù)必須在這個起始任務(wù)中來調(diào)用。 注意:uC/OS-II不允許在中斷服務(wù)程序中創(chuàng)建任務(wù)93 下面是創(chuàng)建任務(wù)的示意性
溫馨提示
- 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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025至2030年中國雙杯壺數(shù)據(jù)監(jiān)測研究報告
- 2025年中國驛風(fēng)味板鴨市場調(diào)查研究報告
- 建筑行業(yè)內(nèi)部承包合同
- 公司參股合作協(xié)議書范本
- 新材料研發(fā)居間合同補充
- 工程建設(shè)鏟車租賃合同范本
- 家裝地暖合同
- 學(xué)校保安聘用合同范本
- 工程安全協(xié)議書
- 交通運輸協(xié)調(diào)居間服務(wù)合同
- 上海中學(xué)國際部幼升小面試真題
- 贏在團(tuán)隊執(zhí)行力課件
- 慢性胰腺炎課件
- 北京理工大學(xué)應(yīng)用光學(xué)課件第四章
- 陰道鏡幻燈課件
- 2022年山東司法警官職業(yè)學(xué)院單招語文試題及答案解析
- PCB行業(yè)安全生產(chǎn)常見隱患及防范措施課件
- DB32∕T 186-2015 建筑消防設(shè)施檢測技術(shù)規(guī)程
- 2022年福建泉州中考英語真題【含答案】
- 汽車座椅骨架的焊接夾具畢業(yè)設(shè)計說明書(共23頁)
- 露天礦山職業(yè)危害預(yù)先危險分析表
評論
0/150
提交評論