




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
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的初始化和啟動(dòng)33.1 3.1 任務(wù)的基本概念任務(wù)的基本概念3.1.1 任務(wù)及其內(nèi)存結(jié)構(gòu) 在設(shè)計(jì)一個(gè)較為復(fù)雜的應(yīng)用程序時(shí),通常把一個(gè)大型任務(wù)分解成多個(gè)小任務(wù),然后在計(jì)算機(jī)中通過運(yùn)行這些小任務(wù),最終達(dá)到完成大任務(wù)的目的。實(shí)時(shí)應(yīng)用程序的設(shè)計(jì)過程包括如何把問題分割成多個(gè)任務(wù)。每個(gè)任務(wù)都是整個(gè)應(yīng)用程序的一部分,
2、都被賦予一定的優(yōu)先級(jí),有自己的一套CPU寄存器和棧空間。由于這種方法可以使系統(tǒng)并發(fā)地運(yùn)行多個(gè)任務(wù),從而提高處理器的利用率,加快程序的執(zhí)行速度,因此現(xiàn)代操作系統(tǒng)幾乎都是多任務(wù)操作系統(tǒng)。 4 一個(gè)任務(wù),也稱作一個(gè)線程,是一個(gè)簡(jiǎn)單的程序,與大任務(wù)分割成的小任務(wù)對(duì)應(yīng)的程序?qū)嶓w就叫做“任務(wù)”,而C/OS-II就是一個(gè)能對(duì)這些小任務(wù)的運(yùn)行進(jìn)行管理和調(diào)度的多任務(wù)操作系統(tǒng)。 從代碼上看,C/OS-II的任務(wù)就是一個(gè)函數(shù)。而從任務(wù)的存儲(chǔ)結(jié)構(gòu)上看,C/OS-II的任務(wù)由三個(gè)部分組成:任務(wù)程序代碼(函數(shù))、任務(wù)堆棧和任務(wù)控制塊。其中任務(wù)控制塊就是關(guān)聯(lián)了任務(wù)代碼的程序控制塊(TCB),它記錄了任務(wù)的各個(gè)屬性;任務(wù)堆棧
3、則用來保存任務(wù)的工作環(huán)境;任務(wù)程序代碼就是任務(wù)的執(zhí)行部分。 5PC6 C/OS-II任務(wù)控制塊實(shí)質(zhì)上就是2.4.2節(jié)中所介紹的具有二級(jí)結(jié)構(gòu)的代碼控制塊,只不過用來指向代碼的指針是CPU程序指針(程序計(jì)數(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ù)控制塊鏈表對(duì)任務(wù)進(jìn)行管理,如下圖所示:8 C/OS-II的任務(wù)有兩種:用戶任務(wù)和系統(tǒng)任務(wù)。由應(yīng)用程序設(shè)計(jì)者編寫的任務(wù),叫做用戶任務(wù);由系統(tǒng)提供的任務(wù)叫做系統(tǒng)任務(wù)。用戶任務(wù)是為了解決應(yīng)用問題
4、而編寫的;系統(tǒng)任務(wù)是為應(yīng)用程序提供某種服務(wù)或?yàn)橄到y(tǒng)本身服務(wù)的。目前,在C/OS-II中,最多可以含有64個(gè)任務(wù)(包括用戶任務(wù)和系統(tǒng)任務(wù))。 9 C/OS II 支持64個(gè)任務(wù),每個(gè)任務(wù)有一個(gè)特定的優(yōu)先級(jí)。 任務(wù)的優(yōu)先級(jí)別用數(shù)字表示,0表示的任務(wù)的優(yōu)先級(jí)最高,數(shù)字越大表示的優(yōu)先級(jí)越低。 通過常數(shù)OS_LOWEST_PRIO (在OS_CFG.H中)定義系統(tǒng)的最低優(yōu)先級(jí)別,同時(shí)限定系統(tǒng)能容納的最多任務(wù)數(shù)量。 建議用戶不要使用優(yōu)先級(jí)為0、1、2、3、OS_LOWEST_PRIO-3、 OS_LOWEST_PRIO-2、 OS_LOWEST_PRIO-1、 OS_LOWEST_PRIO-0的任務(wù)。最低
5、的兩個(gè)已被目前版本的系統(tǒng)占用,將來版本可能會(huì)用到其它的。 103.1.2 任務(wù)的狀態(tài) C/OS-II是按照系統(tǒng)中只有一個(gè)CPU來設(shè)計(jì)的,在這種系統(tǒng)中,一個(gè)具體時(shí)刻只會(huì)有一個(gè)任務(wù)占用,及處在運(yùn)行狀態(tài),而其他任務(wù)只能處在其他狀態(tài)。C/OS-II系統(tǒng)中的任務(wù)共有5種狀態(tài): 睡眠態(tài)(睡眠態(tài)(DORMANT):任務(wù)在沒有被配備任務(wù)控制塊或被剝奪了任務(wù)控制塊時(shí)的狀態(tài)叫作任務(wù)的睡眠態(tài)。 就緒態(tài)(就緒態(tài)(READY):如果系統(tǒng)為任務(wù)配備了任務(wù)控制塊且在任務(wù)就緒表中進(jìn)行了就緒登記,則任務(wù)就具備了運(yùn)行的充分條件,這時(shí)的任務(wù)的狀態(tài)叫就緒態(tài)。11 運(yùn)行態(tài)(運(yùn)行態(tài)(RUNNING):):處于就緒態(tài)的任務(wù)如果經(jīng)調(diào)度器判斷
6、獲得了CPU的使用權(quán),則任務(wù)就進(jìn)入運(yùn)行態(tài)。任何時(shí)刻只能有一個(gè)任務(wù)處于運(yùn)行態(tài)。 等待態(tài)(等待態(tài)(WAITING):):正在運(yùn)行的任務(wù),需要等待一段時(shí)間或需要等待一個(gè)事件發(fā)生再運(yùn)行時(shí),該任務(wù)就會(huì)把CPU的使用權(quán)讓給其他任務(wù)而使任務(wù)進(jìn)入waiting狀態(tài)。 注:進(jìn)入waiting的狀態(tài)有可能是因?yàn)檠訒r(shí),有可能是被掛起,有可能是等待的資源未獲得,總之,uC/OS將所有的已經(jīng)注冊(cè)了的但未就緒的任務(wù)歸為waiting態(tài)。 被中斷態(tài)(被中斷態(tài)(ISR):):正在運(yùn)行的任務(wù)是可以被中斷的,除非該任務(wù)將中斷關(guān)了,或者uC/OS-將中斷關(guān)了。被中斷了的任務(wù)就進(jìn)入了中斷服務(wù)態(tài)(ISR)。 當(dāng)所有的任務(wù)都在等待事件發(fā)
7、生或等待延遲時(shí)間結(jié)束,uC/OS-執(zhí)行空閑任務(wù)(idle task),執(zhí)行OSTaskIdle() 函數(shù)。 12 在系統(tǒng)的管理下,一個(gè)任務(wù)可以在5個(gè)不同的狀態(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ù)的工作特點(diǎn),任務(wù)的執(zhí)行代碼通常是一個(gè)無限循環(huán)結(jié)構(gòu)(對(duì)于一些一次性任務(wù)例外),并且在這個(gè)循環(huán)中可以響應(yīng)中斷,這種結(jié)構(gòu)也叫做超循環(huán)結(jié)構(gòu)。例3-1就是一個(gè)具有超循環(huán)結(jié)構(gòu)的任務(wù)的示意性代碼。 15 例3-1 一個(gè)用C語言編寫的任務(wù) void MyTask(void * pdata)
8、 for( ; ; )可以被中斷的用戶代碼;OS_ENTER_CRITICAL();/進(jìn)入臨界段(關(guān)中斷)不可以被中斷的用戶代碼;OS_EXIT_CRITICAL();/退出臨界段(開中斷)可以被中斷的用戶代碼; 從程序的角度來看,一個(gè)C/OS-II任務(wù)的代碼就是一個(gè)C語言函數(shù)。之所以把任務(wù)的參數(shù)定義成一個(gè)void類型的指針,是為了傳遞各種不同類型的數(shù)據(jù)。16 為了有效的對(duì)中斷進(jìn)行控制,在任務(wù)的代碼里可使用uC/OS-II定義的宏OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()來控制何時(shí)響應(yīng)中斷,何時(shí)屏蔽中斷。這兩個(gè)宏之間的代碼時(shí)是不會(huì)響應(yīng)中斷的,這種受保護(hù)的代碼段
9、叫臨界段。 代碼的臨界段也稱為臨界區(qū),指處理時(shí)不可分割的代碼。一旦這部分代碼開始執(zhí)行,則不允許任何中斷打入。為確保臨界段代碼的執(zhí)行不被中斷,在進(jìn)入臨界段之前必須關(guān)中斷,而臨界段代碼執(zhí)行完后,要立即開中斷。 17 2用戶應(yīng)用程序的一般結(jié)構(gòu) 從程序代碼來看,用戶任務(wù)就是一個(gè)C語言函數(shù),但這個(gè)函數(shù)不是自主函數(shù)main()調(diào)用的函數(shù),在系統(tǒng)中它與主函數(shù)main()處于平等的地位,它們何時(shí)被運(yùn)行以及何時(shí)被終止是由操作系統(tǒng)來調(diào)度的。但要注意,main()畢竟是一個(gè)應(yīng)用程序的主函數(shù),是程序運(yùn)行的入口點(diǎn),所以雖然它不調(diào)用任務(wù),但要負(fù)責(zé)任務(wù)的創(chuàng)建并將它們交給系統(tǒng),至于何時(shí)運(yùn)行它們,則與主函數(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();/啟動(dòng)啟動(dòng) C/OS-II20 其中,OSTaskCreate()是C/OS-II提供的用來創(chuàng)建任務(wù)的函數(shù);OSStart()啟動(dòng)C/OS-II的函數(shù)。系統(tǒng)被啟動(dòng)后,任務(wù)就由操作系統(tǒng)來管理和調(diào)度了。 213.1.4 系統(tǒng)任務(wù) 作為管理者,操作系統(tǒng)除了要管理用戶任務(wù)之外,可能會(huì)有一些內(nèi)部事務(wù)需要處理,最起碼要有一個(gè)沒有用戶任務(wù)可執(zhí)行時(shí)需要做的事情,因?yàn)橛?jì)算機(jī)是不能停下來的。為了與用戶任務(wù)相區(qū)別,這種系統(tǒng)自己所需要的任務(wù)叫做系統(tǒng)任務(wù)。C/OS-II預(yù)定義了兩個(gè)系統(tǒng)任務(wù):空閑任務(wù)和統(tǒng)計(jì)任務(wù)。其中空閑任務(wù)是每個(gè)應(yīng)用程序必須使
12、用的,而統(tǒng)計(jì)任務(wù)則是應(yīng)用程序可以根據(jù)實(shí)際需要來選擇使用的。 22 1. 空閑任務(wù) C/OS-II總要建立一個(gè)空閑任務(wù)(idle task),這個(gè)任務(wù)在沒有其他任務(wù)進(jìn)入就緒狀態(tài)時(shí)投入運(yùn)行。這個(gè)空閑任務(wù)OSTaskIdle()永遠(yuǎn)設(shè)為最低優(yōu)先級(jí),即OS_LOWER_PRIO??臻e任務(wù)OSTaskIdle()的代碼如下: void OSTaskIdle( void * pdata) pdata = pdata; /防止某些編譯器報(bào)錯(cuò) for(;) OS_ENTER_CRITICAL(); /關(guān)閉中斷 OSIdleCtr+; /計(jì)數(shù) OS_EXIT_CRITICAL(); /開放中斷 C/OS-II規(guī)
13、定,一個(gè)用戶應(yīng)用程序必須使用這個(gè)空閑任務(wù),而且這個(gè)任務(wù)是不能用程序來刪除的。23 2統(tǒng)計(jì)任務(wù) C/OS-II提供的另一個(gè)系統(tǒng)任務(wù)就是統(tǒng)計(jì)任務(wù)OSTaskStat( ) OSTaskStat( )每秒運(yùn)行1次,計(jì)算CPU利用率,即告訴用戶應(yīng)用程序使用了多少CPU時(shí)間,用百分比表示,精確度為1%。 如果將系統(tǒng)頭文件OS_CFG.H中的系統(tǒng)配置常數(shù)OS_TASK_STAT_EN設(shè)置為1,統(tǒng)計(jì)任務(wù)就會(huì)在操作系統(tǒng)初始化函數(shù)OSInit( )中調(diào)用OS_InitTaskStat()函數(shù)創(chuàng)建創(chuàng)建。24 在系統(tǒng)調(diào)用多任務(wù)啟動(dòng)函數(shù)OSStart( )之前,用戶初始代碼中必須先建立至少一個(gè)用戶任務(wù)(如TaskSt
14、art),如果應(yīng)用程序打算使用統(tǒng)計(jì)任務(wù),需要在TaskStart任務(wù)中調(diào)用函數(shù) OSStatInit( )對(duì)統(tǒng)計(jì)任務(wù)進(jìn)行初始化初始化。之后再建立應(yīng)用程序中的其他任務(wù)。 應(yīng)該在用戶任務(wù)中(第一個(gè)任務(wù))啟動(dòng)時(shí)鐘節(jié)拍。因?yàn)橛脩舨幌M诙嗳蝿?wù)還沒有開始時(shí)就收到時(shí)鐘節(jié)拍中斷25void main (void)OSInit(); /初初 始化始化uC/OS-II /* 創(chuàng)建用戶起始任務(wù)創(chuàng)建用戶起始任務(wù)(以以TaskStart()作為起始任務(wù),也可以創(chuàng)建多個(gè)任務(wù)作為起始任務(wù),也可以創(chuàng)建多個(gè)任務(wù))*/OSStart(); /開開 始多任務(wù)調(diào)度始多任務(wù)調(diào)度void TaskStart (void *pdata)
15、/* 在這里安裝并啟動(dòng)在這里安裝并啟動(dòng)uC/OS-II的時(shí)鐘節(jié)拍的時(shí)鐘節(jié)拍 */OSStatInit(); / 初始化統(tǒng)計(jì)任務(wù)初始化統(tǒng)計(jì)任務(wù) /* 創(chuàng)建用戶應(yīng)用程序任務(wù)創(chuàng)建用戶應(yīng)用程序任務(wù) */for (;) /* 這里是這里是TaskStart()的代碼的代碼 */ OSTimeDly(10); /調(diào)用該函數(shù)的任務(wù)將自己延時(shí)調(diào)用該函數(shù)的任務(wù)將自己延時(shí)1010個(gè)時(shí)鐘并執(zhí)行一次任務(wù)調(diào)度個(gè)時(shí)鐘并執(zhí)行一次任務(wù)調(diào)度 263.1.5 任務(wù)的優(yōu)先權(quán)及優(yōu)先級(jí)別 uC/OS-II分為64個(gè)優(yōu)先級(jí)別,每一個(gè)級(jí)別都用一個(gè)數(shù)字表示。數(shù)字0的級(jí)別最高,數(shù)字越大優(yōu)先級(jí)別越低。 通常,一個(gè)應(yīng)用程序的任務(wù)數(shù)小于64,用戶可
16、根據(jù)應(yīng)用程序的需要,在OS_CFG.H中設(shè)置OS_LOWEST_PRIO,即定義了可供使用的優(yōu)先級(jí)別共OS_LOWEST_PRIO +1個(gè)。 固定地,系統(tǒng)總是把最低優(yōu)先級(jí)別自動(dòng)賦給空閑任務(wù),如果系統(tǒng)中還有統(tǒng)計(jì)任務(wù),則其優(yōu)先級(jí)別為OS_LOWEST_PRIO -1。因此用戶任務(wù)可以使用的優(yōu)先級(jí)別是0,1,2,.,OS_LOWEST_PRIO-2,共OS_LOWEST_PRIO-1個(gè) 27 例:如果希望應(yīng)用程序中任務(wù)的優(yōu)先級(jí)別為28個(gè),則表示最低優(yōu)先級(jí)別的常數(shù)OS_LOWEST_PRIO值應(yīng)該是多少?如果應(yīng)用程序中使用了系統(tǒng)提供的空閑任務(wù)和統(tǒng)計(jì)任務(wù),則該應(yīng)用程序最多可以安排多少個(gè)任務(wù)? 28 答:
17、表示最低優(yōu)先級(jí)別的常數(shù)OS_LOWEST_PRIO值應(yīng)該為27,優(yōu)先級(jí)別分別為0,1,2,3,.,27;由于系統(tǒng)空閑任務(wù)占用了優(yōu)先級(jí)別27,統(tǒng)計(jì)任務(wù)占用了優(yōu)先級(jí)別26,則應(yīng)用程序中最多可以安排優(yōu)先級(jí)別分別為0,1,2,.,25的26個(gè)任務(wù)。29 給某一個(gè)用戶任務(wù)的定義優(yōu)先級(jí)別,需要在調(diào)用系統(tǒng)函數(shù)OSTaskCreate()來創(chuàng)建任務(wù)時(shí),用該函數(shù)的第4個(gè)參數(shù)prio來指定。 由于每個(gè)任務(wù)都具有惟一的優(yōu)先級(jí)別,因此C/OS-II通常也用任務(wù)的優(yōu)先級(jí)別來作為這個(gè)任務(wù)的標(biāo)識(shí)。 303.2 3.2 任務(wù)堆棧任務(wù)堆棧 任務(wù)堆棧是任務(wù)的重要組成部分。 所謂堆棧,就是在存儲(chǔ)器中按數(shù)據(jù)“后進(jìn)先出(LIFO)”的
18、原則組織的連續(xù)存儲(chǔ)空間。為了滿足任務(wù)切換和響應(yīng)中斷時(shí)保存CPU寄存器中的內(nèi)容及任務(wù)調(diào)用其他函數(shù)時(shí)的需要,每個(gè)任務(wù)都有自己的棧空間。所有C/OS-II任務(wù)的任務(wù)控制塊中都含有一個(gè)指向該任務(wù)堆棧的指針。31 C/OS-II中堆棧的數(shù)據(jù)類型為為OS_STK,在文件OS_CPU.H中定義: typedef unsigned int OS_STK; /該類型長度為該類型長度為16位位 這樣,在應(yīng)用程序中定義任務(wù)堆棧的棧區(qū)就非常簡(jiǎn)單,即定義一個(gè)OS_STK類型的一個(gè)數(shù)組即可。例如:#define TASK_STK_SIZE 512 /定義堆棧的長度定義堆棧的長度(1024字節(jié)字節(jié))OS_STK TaskS
19、tkTASK_STK_SIZE; /定義一個(gè)數(shù)組來作為任務(wù)堆棧定義一個(gè)數(shù)組來作為任務(wù)堆棧 當(dāng)調(diào)用函數(shù)OSTaskCreate()來創(chuàng)建一個(gè)任務(wù)時(shí),把數(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)先級(jí)別的參數(shù)指定任務(wù)優(yōu)先級(jí)別的參數(shù) ); 使用例3-1的代碼來作為任務(wù)代碼來創(chuàng)建一個(gè)任務(wù)MyTask,任務(wù)堆棧的長度為128字節(jié),優(yōu)先級(jí)別為20,任務(wù)參數(shù)pdata的實(shí)參為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)先級(jí)別任務(wù)的優(yōu)先級(jí)別 34 堆棧的增長方向是隨系統(tǒng)所使用的處理器不同而不同。因此在使用函數(shù)OSTaskCreate() 創(chuàng)建任務(wù)時(shí),一定要注意所使用的處理器對(duì)堆棧增長方向的支持是向上的還是向下的。 35 上一練習(xí)時(shí)假設(shè)使用了支持堆棧向下增長方式的處理器設(shè)置參數(shù)ptos。如果使用的處理器支持堆棧的增長方向向上,則應(yīng)該為: OSTaskCreate( MyTask, &MytaskAgu, &MyTaskStk0, 20); 為了提高應(yīng)用程序的移植性,在編寫代碼時(shí)可兼顧兩種情況,利用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)先級(jí)別任務(wù)的優(yōu)先級(jí)別#else OSTaskCreate( MyTa
23、sk, /任務(wù)的指針任務(wù)的指針 &MyTaskAgu, /傳遞給任務(wù)的參數(shù)傳遞給任務(wù)的參數(shù) &MyTaskStk0, /任務(wù)堆棧棧頂?shù)刂啡蝿?wù)堆棧棧頂?shù)刂?20); /任務(wù)的優(yōu)先級(jí)別任務(wù)的優(yōu)先級(jí)別#endif 373.2.2 任務(wù)堆棧的初始化 當(dāng)CPU啟動(dòng)運(yùn)行一個(gè)任務(wù)時(shí),CPU的各寄存器總是需要預(yù)置一些初始數(shù)據(jù),例如指向任務(wù)的指針、任務(wù)堆棧指針、程序狀態(tài)字等。那么,系統(tǒng)啟動(dòng)任務(wù)時(shí),CPU從何處可以獲得這些數(shù)據(jù)呢?最方便的方法就是讓CPU從這個(gè)任務(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 ); 通常用戶不會(huì)直接接觸到這個(gè)函數(shù),該函數(shù)由C/OS-II所提供的任務(wù)創(chuàng)建函數(shù)OSTaskCreate()來調(diào)用。 由于各處理器的寄存器及對(duì)堆棧的操作方式不同,因此該函數(shù)需要用戶在進(jìn)行C/OS-II的移植時(shí),按所使用的處理器由用戶來編寫。 393.3任務(wù)控制塊(TCB)及任務(wù)控制塊鏈表 C/OS-II用來記錄任務(wù)的堆棧指針、任務(wù)的當(dāng)前狀態(tài)、任務(wù)的優(yōu)先級(jí)別
25、等一些與任務(wù)管理有關(guān)的屬性的表就叫做任務(wù)控制塊。 C/OS-II把系統(tǒng)所有任務(wù)的控制塊鏈接為兩條鏈表,并通過它們管理各個(gè)任務(wù)。40 一旦任務(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ù)的身份證,沒有任務(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; /指向后一個(gè)任務(wù)控制塊的指針指向后一個(gè)任務(wù)控制塊的指針 struct os_tcb *OSTCBPrev; /指向前一個(gè)任務(wù)控制塊的指針指向前一個(gè)任務(wù)控制塊的指針 INT16U OSTCBDly; /任務(wù)等待的時(shí)限(節(jié)拍數(shù))任務(wù)等待的時(shí)限(節(jié)拍數(shù)) 當(dāng)需要把任務(wù)延時(shí)若干時(shí)鐘節(jié)拍時(shí),或者需要把任務(wù)掛起一段時(shí)間當(dāng)需要把任務(wù)延時(shí)若干時(shí)鐘節(jié)拍時(shí),或者需要把任務(wù)掛起一段時(shí)間
27、以等待某事件的發(fā)生時(shí)需要用到這個(gè)變量。如果這個(gè)變量為以等待某事件的發(fā)生時(shí)需要用到這個(gè)變量。如果這個(gè)變量為0,表示,表示任務(wù)不延時(shí),或者表示等待事件發(fā)生的時(shí)間沒有限制任務(wù)不延時(shí),或者表示等待事件發(fā)生的時(shí)間沒有限制 。 INT8U OSTCBStat; /任務(wù)的當(dāng)前狀態(tài)標(biāo)志任務(wù)的當(dāng)前狀態(tài)標(biāo)志 INT8U OSTCBPrio; /任務(wù)的優(yōu)先級(jí)別任務(wù)的優(yōu)先級(jí)別 OS_TCB;42 其中OSTCBStat:任務(wù)狀態(tài)字,可取下列值: OS_STAT_RDY: 處于就緒狀態(tài) OS_STAT_SEM: 處于等待信號(hào)量狀態(tài) OS_STAT_MBOX:處于等待郵箱狀態(tài) OS_STAT_Q: 處于等待消息隊(duì)列狀態(tài)
28、OS_STAT_SUSPEND:處于被掛起狀態(tài) OS_STAT_MUTEX:處于等待互斥信號(hào)量狀態(tài)433.3.2 任務(wù)控制塊鏈表兩條鏈表來管理任務(wù)控制塊: 空任務(wù)塊鏈表(所有任務(wù)控制塊還沒有分配給任務(wù)),是在應(yīng)用程序調(diào)用函數(shù)OSInit( )對(duì)系統(tǒng)進(jìn)行初始化時(shí)建立的。 任務(wù)塊鏈表(所有任務(wù)控制塊已經(jīng)分配給任務(wù)),是在調(diào)用函數(shù)OSTaskCreate( )創(chuàng)建任務(wù)時(shí)建立的。建立任務(wù)控制塊鏈表的具體做法是,從空鏈表摘取一個(gè)空任務(wù)控制塊,然后填充上任務(wù)屬性后再形成新的鏈表。44 系統(tǒng)在調(diào)用函數(shù)OSInit()對(duì)C/OS-II系統(tǒng)進(jìn)行初始化時(shí),先在RAM中建立一個(gè)OS_TCB結(jié)構(gòu)類型的數(shù)組OSTCBT
29、bl ,每個(gè)數(shù)組元素就是一個(gè)任務(wù)控制塊,然后把這些控制塊鏈接成一個(gè)如圖所示的鏈表。由于鏈表中的這些控制塊還沒有與具體任務(wù)相關(guān)聯(lián),因此這個(gè)鏈表叫做空任務(wù)塊鏈表OSTCBFreeList。45 每當(dāng)應(yīng)用程序調(diào)用系統(tǒng)函數(shù)OSTaskCreate()創(chuàng)建一個(gè)任務(wù)時(shí),系統(tǒng)就會(huì)將任務(wù)控制塊鏈表頭指針OSTCBFreeList指向的任務(wù)控制塊分配給該任務(wù)。在給任務(wù)控制塊中的各成員賦值后,就按任務(wù)控制塊鏈表的頭指針OSTCBList將其加入到任務(wù)控制塊鏈表中。 下圖是在上圖空任務(wù)控制塊鏈表基礎(chǔ)上,應(yīng)用程序創(chuàng)建了兩個(gè)用戶任務(wù)并使用了兩個(gè)系統(tǒng)任務(wù)(空閑任務(wù)和統(tǒng)計(jì)任務(wù))的情況時(shí),空任務(wù)塊鏈表和任務(wù)塊鏈表的結(jié)構(gòu)示意圖
30、(圖中陰影區(qū)域?yàn)槿蝿?wù)塊鏈表)。 46473.3.3 任務(wù)控制塊初始化 當(dāng)用戶程序調(diào)用函數(shù)OSTaskCreate() 創(chuàng)建一個(gè)任務(wù)時(shí),這個(gè)函數(shù)會(huì)調(diào)用系統(tǒng)函數(shù)OSTCBInit() 來為任務(wù)控制塊進(jìn)行初始化。任務(wù)控制塊初始化函數(shù)OSTCBInit()做三件事:1、從空任務(wù)控制塊鏈表中獲取一個(gè)任務(wù)控制塊;2、用任務(wù)的屬性值對(duì)任務(wù)控制塊各個(gè)成員進(jìn)行賦值;3、把這個(gè)任務(wù)控制塊鏈入到任務(wù)控制塊使用鏈表的頭部。48 初始化任務(wù)控制塊函數(shù)OSTCBInit() 的原型如下:INT8U OSTCBInit(INT8U Prio,/任務(wù)的優(yōu)先級(jí)別,保存在任務(wù)的優(yōu)先級(jí)別,保存在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ù)的控制塊的選擇項(xiàng),保存在任務(wù)的控制塊的選擇項(xiàng),保存在OSTCBOpt中中)
32、;493.4 任務(wù)就緒表及任務(wù)調(diào)度 多任務(wù)操作系統(tǒng)的核心:任務(wù)調(diào)度。 調(diào)度定義:就是通過一個(gè)算法在多個(gè)任務(wù)中確定哪個(gè)任務(wù)來運(yùn)行。做這項(xiàng)工作的就是調(diào)度器。 任務(wù)調(diào)度的思想:總是讓優(yōu)先級(jí)最高的就緒任務(wù)處于運(yùn)行狀態(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è)立了一個(gè)記錄表,系統(tǒng)中的每個(gè)任務(wù)都在這個(gè)表占據(jù)一個(gè)位置,并用這個(gè)位置的狀態(tài)( 1或者0)來表示任務(wù)是否處于就緒狀態(tài)。這個(gè)表就叫做任務(wù)就緒表。 513.4.1 任務(wù)就緒表結(jié)構(gòu) 每個(gè)就緒的任務(wù)都放入就緒表中(rea
33、dy list)中,就緒表用兩個(gè)變量表示:OSRdyGrp、OSRdyTbl 。在OSRdyGrp中,任務(wù)按優(yōu)先級(jí)分組,8個(gè)任務(wù)為一組。OSRdyGrp中的每一位表示8組任務(wù)中每一組是否有進(jìn)入就緒態(tài)的任務(wù)。任務(wù)進(jìn)入就緒態(tài)時(shí),就緒表OSRdyTbl 中的相應(yīng)元素的相應(yīng)位也置為1。OSRdyGrp和OSRdyTbl 之間的關(guān)系見下圖,它們之間的關(guān)系是按照以下規(guī)則給出的:當(dāng)當(dāng)OSRdyTbl0中的任何一位是中的任何一位是1時(shí),時(shí),OSRdyGrp的第的第0位置位置1;當(dāng)當(dāng)OSRdyTbl1中的任何一位是中的任何一位是1時(shí),時(shí),OSRdyGrp的第的第1位置位置1;當(dāng)當(dāng)OSRdyTbl2中的任何一位是
34、中的任何一位是1時(shí),時(shí),OSRdyGrp的第的第2位置位置1;當(dāng)當(dāng)OSRdyTbl3中的任何一位是中的任何一位是1時(shí),時(shí),OSRdyGrp的第的第3位置位置1;5253 就緒表OSRdyTbl 數(shù)組的大小取決于OS_LOWEST_PR1O(見文件OS_CFG.H)。當(dāng)用戶的應(yīng)用程序中任務(wù)數(shù)目比較少時(shí),減少OS_LOWEST_PR1O 的值可以降低C/OS-對(duì)RAM(數(shù)據(jù)空間)的需求量。 那么如何根據(jù)任務(wù)的優(yōu)先級(jí)別查找任務(wù)在就緒表的位置呢? 從圖中可以看出,由于優(yōu)先級(jí)別是一個(gè)單字節(jié)的數(shù)字,而且最大值不會(huì)超過63,即二進(jìn)制00111111,因此,可以把優(yōu)先級(jí)別看成是一個(gè)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:已知某一個(gè)已經(jīng)就緒的任務(wù)優(yōu)先級(jí)別為prio=30,試判斷應(yīng)該在就緒表的哪一位置上置1。 答:30的二進(jìn)制形式為00011110,其低6位為011110,于是可知應(yīng)該把變量OSRdyGrp的D3位置1 , 同時(shí)要在OSRdyTbl3 的D6位上置1 。55 根據(jù)就緒表確定最高優(yōu)先級(jí)兩個(gè)關(guān)鍵:n優(yōu)先級(jí)數(shù)分解為高三位和低三位分別確定;n高優(yōu)先級(jí)有著小的優(yōu)先級(jí)號(hào) 。563.4.2 對(duì)任務(wù)就緒表的操作 系統(tǒng)對(duì)于就緒表主要有三個(gè)操作:登記、注銷和
36、從就緒表的就緒任務(wù)中得知具有最高優(yōu)先級(jí)任務(wù)的標(biāo)識(shí)(優(yōu)先級(jí)prio)。 57 1. 登記 登記:指的是當(dāng)某個(gè)任務(wù)處于就緒狀態(tài)時(shí),系統(tǒng)將該任務(wù)登記在任務(wù)就緒表中,即在就續(xù)表中將該任務(wù)的對(duì)應(yīng)位置1。 在程序中,可用類似于下面的代碼把優(yōu)先級(jí)為prio的任務(wù)置為就緒態(tài):OSRdyGrp | = OSMapTblprio3;OSRdyTblprio3 | = OSMapTblprio & 0 x07; 其中,OSMapTbl 是C/OS-II為加快運(yùn)算速度定義的一個(gè)數(shù)組,各元素為:OSMapTbl0 = 0000 0001BOSMapTbl1 = 0000 0010BOSMapTbl2 = 000
37、0 0100BOSMapTbl3 = 0000 1000BOSMapTbl4 = 0001 0000BOSMapTbl5 = 0010 0000BOSMapTbl6 = 0100 0000BOSMapTbl7 = 1000 0000B58 例1:使優(yōu)先級(jí)為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)先級(jí)為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)某個(gè)任務(wù)需要脫離就緒狀態(tài)時(shí),系統(tǒng)在就緒表中將該任務(wù)的對(duì)應(yīng)位置0。 如果要使一個(gè)優(yōu)先級(jí)別為prio的任務(wù)脫離就緒狀態(tài),
39、則可使用如下代碼:If(OSRdyTblprio3&= OSMapTblprio & 0 x07)=0)OSRdyGrp&= OSMapTblprio3; 脫離就緒態(tài):將任務(wù)就緒表OSRdyTblprio3相應(yīng)元素的相應(yīng)位清零,而且當(dāng)OSRdyTblprio3中的所有位都為零時(shí),即全組任務(wù)中沒有一個(gè)進(jìn)入就緒態(tài)時(shí),OSRdyGrp的相應(yīng)位才為零。 63 例:使優(yōu)先級(jí)為12的任務(wù)脫離就緒表 答: 欲使優(yōu)先級(jí)為12的任務(wù)進(jìn)入就緒態(tài) 優(yōu)先級(jí)為12,即00001100BOSRdyGrp | = OSMapTblprio 3 ; (OSMapTbl1 = 0000 0010)OSR
40、dyTbl1 | = OSMapTblprio &0 x07 ; (OSMapTbl4 = 0001 0000) 欲使優(yōu)先級(jí)為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)先級(jí)最高的任務(wù) 從
41、任務(wù)就緒表中獲取優(yōu)先級(jí)別最高的就緒任務(wù)可用如下代碼:y = OSUnMapTblOSRdyGrp;/獲得優(yōu)先級(jí)別的獲得優(yōu)先級(jí)別的D5、D4、D3位位x = OSUnMapTblOSRdyTbly;/獲得優(yōu)先級(jí)別的獲得優(yōu)先級(jí)別的D2、D1、D0位位Prio =(y3)+x;/獲得就緒任務(wù)的優(yōu)先級(jí)別獲得就緒任務(wù)的優(yōu)先級(jí)別 或y = OSUnMapTblOSRdyGrp;Prio = (INT8U)(y3)+OSUnMapTblOSRdyTbly);66 該代碼執(zhí)行后,得到的是最高優(yōu)先級(jí)就緒任務(wù)的優(yōu)先級(jí)別。其中,OSUnMapTbl同樣是C/OS-II為加快運(yùn)算速度定義的一個(gè)數(shù)組,共有256個(gè)元素,
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)先級(jí)最高的任務(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)先級(jí)最高的任務(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)前正在運(yùn)行的任務(wù)而去運(yùn)行另一個(gè)任務(wù)的工作。 任務(wù)調(diào)度:按某種規(guī)則進(jìn)行任務(wù)切換的工作。 調(diào)度的發(fā)生條件:系統(tǒng)或用戶任務(wù)調(diào)用系統(tǒng)函數(shù)或者執(zhí)行中斷服務(wù)程序結(jié)束時(shí)。 任務(wù)調(diào)度由任務(wù)調(diào)度器完成,調(diào)度器主要工作:1)在任務(wù)就緒表中查找具有最高優(yōu)先級(jí)別的就緒任務(wù)。2)實(shí)現(xiàn)任務(wù)切換。 C/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ù)的切換。 72 2. 獲得待運(yùn)行任務(wù)的TCB指針 由于操作系統(tǒng)是通過任務(wù)的任務(wù)控
48、制塊TCB來管理任務(wù)的,因此調(diào)度器真正實(shí)施任務(wù)切換之前的主要工作就是要獲得待運(yùn)行任務(wù)的任務(wù)控制塊指針和當(dāng)前任務(wù)的任務(wù)控制塊指針。 任務(wù)級(jí)的調(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)先級(jí)別
49、就緒任務(wù)的優(yōu)先級(jí)別OSPrioHighRdy;然后在確認(rèn)了這個(gè)就緒任務(wù)不是當(dāng)前正在運(yùn)行的任務(wù)(OSPrioCur是存放正在運(yùn)行任務(wù)的優(yōu)先級(jí)別的變量)的條件下,用OSPrioHighRdy作為下標(biāo)去訪問數(shù)組OSTCBPrioTbl,把數(shù)組元素OSTCBPrioTblOSPrioHighRdy的值(即待運(yùn)行就緒任務(wù)的任務(wù)控制塊指針)付給指針變量OSTCBHighRdy。于是可以依據(jù)OSTCBHighRdy和OSTCBCur這兩個(gè)分別指向待運(yùn)行任務(wù)控制塊和當(dāng)前任務(wù)控制塊的指針在宏OS_TASK_SW( )中實(shí)施任務(wù)切換了。 763. 任務(wù)切換OS_TASK_SW( )任務(wù)級(jí)的任務(wù)切換需完成以下2步操
50、作: 將被掛起任務(wù)的處理器寄存器推入堆棧 將較高優(yōu)先級(jí)任務(wù)的寄存器值從堆棧中恢復(fù)到寄存器中 任務(wù)級(jí)的任務(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)造了一個(gè)假想的CPU,該CPU有8個(gè)寄存器:1個(gè)堆棧指針(SP);1個(gè)程序計(jì)數(shù)器(PC);1個(gè)處理器狀態(tài)寄存器(PSW);4個(gè)通用寄存器(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中。此時(shí),CPU的SP寄存器和OSTCBCurOSTCBStkPtr都指向當(dāng)前任務(wù)堆棧的同一位置81 下圖3示意執(zhí)行任務(wù)切換最后一段代碼之后變量和數(shù)據(jù)結(jié)構(gòu)的狀況:重新裝入要運(yùn)行的任務(wù)82(1) 由于新的當(dāng)前任務(wù)是將要重新開始運(yùn)行的任務(wù),任務(wù)切換代碼將OSTCBHighRdy復(fù)制到OSTCBCur(2) 從OS_TCB中
52、找出將要重新開始運(yùn)行的任務(wù)的堆棧指針(在OSTCBHighRdyOSTCBStkPtr中),裝入CPU的SP寄存器中。此時(shí),SP寄存器指向堆棧中存有寄存器R4值的位置(3) 按相反的方向從堆棧中彈出通用寄存器(4) 通過執(zhí)行中斷返回指令,PC和PSW的值裝回到CPU中。此時(shí),由于程序計(jì)數(shù)器PC的值變了,重新開始運(yùn)行的任務(wù)代碼從PC指向的那一點(diǎn)開始運(yùn)行,于是切換到新任務(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有兩個(gè)用來創(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)建一個(gè)任務(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)先級(jí))87void *psp;INT8U err;if (prio OS_LOWEST_PRIO) /任務(wù)的優(yōu)先級(jí)必須在0到OS_LOWEST_PRI
55、O/之間檢測(cè)任務(wù)的優(yōu)先級(jí)是否合法 return (OS_PRIO_INVALID);OS_ENTER_CRITICAL();if (OSTCBPrioTblprio = (OS_TCB *)0) / 確認(rèn)優(yōu)先級(jí)未被使用 OSTCBPrioTblprio = (OS_TCB *)1; / 如果擬分配的優(yōu)先級(jí)是空閑的,通過/在OSTCBPrioTbl 中放置一個(gè)非空指針,保留該優(yōu)先級(jí)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池/中獲得并初始化一個(gè)任務(wù)控制塊OS_TCB88if (err = OS_NO_ERR) OS_ENTER_CRITICAL();OSTaskCtr+; / 從OS_TCBInit( )返回后,任務(wù)計(jì)數(shù)器加1,/用于跟蹤已經(jīng)建立了的任務(wù)數(shù)目OS_EXIT_CRITICAL();if ( OSRunning) OSSched(); / 任務(wù)調(diào)度 /如果OSTaskCreate ()函數(shù)是在某個(gè)任務(wù)
57、的執(zhí)行過程中被調(diào)用(OSRunning=1)/則任務(wù)調(diào)度函數(shù)會(huì)被調(diào)用來判斷是否新建立的任務(wù)比原來的任/務(wù)有更高的優(yōu)/先級(jí)。如果新任務(wù)的優(yōu)先級(jí)更高,內(nèi)核會(huì)進(jìn)行一次任務(wù)切換。else OS_ENTER_CRITICAL();OSTCBPrioTblprio = (OS_TCB *)0; / 放棄任務(wù) /從OSTCBInit()返回后,要檢驗(yàn)返回代碼,如果成功,就增加OSTaskCtr, /OSTaskCtr用于保存產(chǎn)生的任務(wù)數(shù)目。如果OSTCBInit()返回失敗,就置 /OSTCBPrioTblprio 的入口為0以放棄該任務(wù)的優(yōu)先級(jí)。OS_EXIT_CRITICAL();return (err
58、); 89else OS_EXIT_CRITICAL();return (OS_PRIO_EXIST);90 從函數(shù)OSTaskCreate( )的源代碼中可以看到,函數(shù)對(duì)待創(chuàng)建任務(wù)的優(yōu)先級(jí)別進(jìn)行一系列判斷,確認(rèn)該優(yōu)先級(jí)別合法且未被使用之后,隨即調(diào)用函數(shù)OSTaskStkInit( )和OSTCBInit( )對(duì)任務(wù)堆棧和任務(wù)控制塊進(jìn)行初始化。初始化成功后,除了把任務(wù)計(jì)數(shù)器加1外,還要進(jìn)一步判斷uC/OS-II的核是否在運(yùn)行狀態(tài)(即OSRunning的值是否為1),如果OSRunning的值為1,則調(diào)用OSSched( )進(jìn)行任務(wù)調(diào)度。 提問:能否調(diào)用OSTaskCreate( )函數(shù)來創(chuàng)建優(yōu)
59、先級(jí)為OS_LOWEST_PRIO的任務(wù)?不能,因?yàn)閮?yōu)先級(jí)OS_LOWEST_PRIO是為空閑任務(wù)保留的。如果這樣做,會(huì)返回代碼出錯(cuò)信息OS_PRIO_EXIST。913.5.2 用函數(shù)OSTaskCreateExt( )創(chuàng)建任務(wù) 用OSTaskCreateExt( )函數(shù)來建立任務(wù)會(huì)更加靈活,但是會(huì)增加一些額外的開銷。函數(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)先級(jí)INT16U id, / 任務(wù)的標(biāo)示OS_STK *pbos, / 任務(wù)堆棧棧底的指針I(yè)NT32U stk_size, / 任務(wù)堆棧的容量void *pext, / 指向附加數(shù)據(jù)域的指針I(yè)NT16U opt / 用于設(shè)置操作選項(xiàng)); 923.5.3 創(chuàng)建任務(wù)的一般方法 可在調(diào)用函數(shù)OSStart( )啟動(dòng)任務(wù)調(diào)度之前來創(chuàng)建。 在任務(wù)中來創(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ù)中來調(diào)用。 注意:uC/OS-II不允許在中斷服務(wù)程序中創(chuàng)建任務(wù)93 下面是創(chuàng)建任務(wù)的示意性
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025屆云南省昆明市祿勸縣一中高三二診模擬考試化學(xué)試卷含解析
- 人工智能在智能交通系統(tǒng)中的應(yīng)用
- 黑龍江省哈爾濱市第十九中學(xué)2025屆高三沖刺模擬化學(xué)試卷含解析
- 河南省重點(diǎn)高中2025屆高三3月份模擬考試化學(xué)試題含解析
- 吉林省通榆縣第一中學(xué)2025屆高考沖刺模擬化學(xué)試題含解析
- 2025年醫(yī)用手套項(xiàng)目發(fā)展計(jì)劃
- 2025年異環(huán)磷酰胺合作協(xié)議書
- 宣傳防疫知識(shí)工作總結(jié)
- 2025年廢舊材料回收加工項(xiàng)目建設(shè)方案
- 四年級(jí)數(shù)學(xué)(四則混合運(yùn)算帶括號(hào))計(jì)算題專項(xiàng)練習(xí)與答案匯編
- (5年高職)商務(wù)談判教學(xué)課件全套電子教案匯總整本書課件最全教學(xué)教程完整版教案(最新)
- 嘉興華雯化工 - 201604
- 骨科手術(shù)學(xué)課件:髖及大腿的手術(shù)入路及部分手術(shù)介紹
- 冀教版七年級(jí)下冊(cè)數(shù)學(xué)課件 第8章 8.2.1 冪的乘方
- 橋梁線形與變形檢測(cè)檢測(cè)方法實(shí)施細(xì)則
- 三級(jí)醫(yī)院服務(wù)能力指南2022
- 除法口訣表(完整高清打印版)
- 部編三年級(jí)語文下冊(cè)詞語表帶拼音
- 中國飲食禮儀(課堂PPT)
- 張素芳--孫重三小兒推拿流派特色與臨床應(yīng)用完整版
- 河北省城市建設(shè)用地性質(zhì)和容積率調(diào)整管理規(guī)定---精品資料
評(píng)論
0/150
提交評(píng)論