




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
第四章μC/OS-Ⅱ內核與面向任務程序設計
4.1μC/OS-Ⅱ內核OS_CORE.C
4.2任務OS_TASK.C
4.3時間OS_TIME.C
4.4本章小結
μC/OS-Ⅱ是多任務的實時操作系統(tǒng),它的工作原理很簡單,這里通過一個實例來說明。例如,一家公司有255個員工,所有這些員工按職位分為255級(即不存在職位相同的員工),公司里只有一個電話總機,每個員工都有一個分機,每個員工打外線電話,都需要通過同一個總機接外線。4.1μC/OS-Ⅱ內核OS_CORE.C假定每個員工每次打電話的時間絕不會超過1分鐘??倷C處有一個接線員管理。公司總經理的職位最高,他打電話的優(yōu)先級為0;第一副經理的職位第二,他打電話的優(yōu)先級為1;依次類推,職位最低的員工打電話的優(yōu)先級為254。因此,公司運作過程中總機電話業(yè)務有以下情況(假設接線員8點0分上班后,每1分鐘視察一下總機,這里的1分鐘即時鐘節(jié)拍):
(1)接線員上班后,打開總機,檢查撥號的電話。如果此時所有員工同時撥號,當然,接線員會使總經理得到總機使用權,其他員工進入隊列。等總經理打完后,再按優(yōu)先級調度,依次接通。
(2)如果在某個時刻總機空閑,此時,任一員工撥號,等到接線員視察總機時進行調度,把總機分配給他。
(3)如果在某個時刻總機空閑,此時,有多個員工同時撥號,等到接線員視察總機時,進行調度,把總機分配給最高職位的員工,其他員工進入等待隊列,等高職位的員工打完后,再依次接通。
(4)如果某個時刻總機正在被某個員工使用,此時,比他職位高的人正在撥號,則等到接線員視察總機時,中斷當前的通話,使職位高的人先接通,等職位高的人打完電話后,再恢復剛才被中斷的員工的通話。如果此時又有多個人撥號,此時,接線員將進行調度,讓被中斷的員工和所有新?lián)芴柕膯T工中職位最高的人先使用總機,其他員工進入等待隊列。從這一步可以看出,如果某個職位低的員工正在使用總機,此時,即使總經理撥號,也必須等到時鐘節(jié)拍來到后(即接線員視察或系統(tǒng)調度時)才能使總經理得到總機,最長等待時間為1分鐘。但是如果該職位低的員工使用完總機后,還沒有到接線員視察總機的時刻,那么總機會自動調度給新?lián)芴柕母呗毼粏T工。即空閑總機不會調度,但是每個員工打完電話后都會自動調度一次。
(5)如果某個時刻總機正在被使用,更高職位的員工緊急撥號,此時,可通過“中斷”通知接線員立即進行調度,使高職位的員工使用總機,中斷原來的通話,使職位低的員工進入中斷狀態(tài)。
從接線員的角度出發(fā)來看待這一問題,其運作過程是這樣的:接線員每隔1分鐘視察一下總機,如果總機空閑,則什么都不做;如果此時只有一人在撥號中,則幫他接通;如果此時有多人在撥號中,則幫職位最高的人接通,把其他人放入等待隊列中,等職位高的人打完電話后,依次按職位高低自動接通;如果接線員在間隔中受到“中斷”指示,則立即進行臨時調度,如果當前有員工在使用總機,則中斷他,使正在撥號的優(yōu)先級最高的人接通電話,其他人進入隊列。每個員工打完電話后,都會自動調度一次,這次調度不需要接線員干預。顯然,接線員相當于總機切換的時鐘節(jié)拍,如果沒有接線員,總機無法切換,只能保持空閑狀態(tài),整個公司的電話業(yè)務就會停止。如果把上述的員工視為任務,接線員視為時鐘節(jié)拍,則μC/OS-Ⅱ的基本工作原理也是如此。在μC/OS-Ⅱ中,創(chuàng)建好若干任務后,一般地,系統(tǒng)按任務的優(yōu)先級依次執(zhí)行一次后,各任務均進入延時等待狀態(tài),時鐘節(jié)拍相當于心臟的脈搏,在每個時鐘節(jié)拍處,將檢查處于就緒態(tài)的任務,進行任務(切換)調度,使就緒態(tài)任務中最高優(yōu)先級的任務得到CPU使用權,其他任務進入等待隊列。每個任務單次運行CPU占用的時間不能大于一個時鐘節(jié)拍。除了系統(tǒng)創(chuàng)建的空閑任務外,用戶創(chuàng)建的任務運行完后,系統(tǒng)將進行一次任務調度。時鐘節(jié)拍用于更新各個任務的延時。上述這種情況是各個任務都是獨立運行、互不通信的情況,μC/OS-Ⅱ允許多個任務間進行數據通信,此時,系統(tǒng)運行稍微復雜一點,即在任務調度時,會檢查用于任務間通信的信號量和郵箱。
所謂的任務,本質上是帶有一個void*指針參數、無返回值的死循環(huán)函數。在μC/OS-ⅡV2.86版本中,用戶最多可以創(chuàng)建252個任務(μC/OS-ⅡV2.86最多支持255個任務,其中,系統(tǒng)創(chuàng)建的3個任務是空閑任務、統(tǒng)計任務和定時器任務)。μC/OS-Ⅱ應用程序就是由一個個的任務組成的,任務中再調用函數完成特定的功能。每個任務具有不同的優(yōu)先級,當一個任務執(zhí)行完成后,把CPU的使用權交給μC/OS-Ⅱ內核,進行任務調度,使處于就緒態(tài)的最高優(yōu)先級任務得到執(zhí)行權。當μC/OS-Ⅱ內核進行任務調度后,去執(zhí)行就緒態(tài)的具有最高優(yōu)先級的任務的過程,不是通常意義下的函數調用(可以說,任務在“創(chuàng)建”時就被調用了),而是μC/OS-Ⅱ意義下的函數“返回”(或稱任務調用),即返回到那個死循環(huán)函數(任務)中執(zhí)行。通常意義下的函數調用是指:①保存當前調用函數(程序)的環(huán)境,程序指針跳轉到被調用函數入口處,執(zhí)行完被調用函數后,從堆棧中恢復調用函數的環(huán)境,繼續(xù)執(zhí)行原程序;②調用函數和被調用函數共用相同的堆棧,實際上被調用函數沒有堆棧;③被調用函數的調用執(zhí)行是由調用函數發(fā)出的;④被調用函數被調用后立即執(zhí)行。而μC/OS-Ⅱ意義下的任務調用是指:①每個任務都有獨立的堆??臻g,μC/OS-Ⅱ下的任務調用是先把當前任務的執(zhí)行環(huán)境保存在它自己的堆棧中,然后從被調用任務的堆?;謴捅徽{用任務的環(huán)境,這兩個任務占用不同的堆??臻g;②被調用任務的入口地址來自其堆棧,而不是函數標號;③被調用函數的調用執(zhí)行是由μC/OS-Ⅱ調度器發(fā)出的,即由μC/OS-Ⅱ內核調用的,而不是某個任務;④被調用任務進入就緒態(tài),即可以執(zhí)行,但有可能不會立即執(zhí)行。所以,一定意義上,任務的調用可以理解為返回到那個函數去執(zhí)行,而不是調用那個函數來執(zhí)行。任務永遠不會返回,當前任務完成特定的功能后,釋放CPU占用權,進入等待態(tài),等待下一個“該函數返回”。CPU空閑時,μC/OS-Ⅱ執(zhí)行系統(tǒng)定義的優(yōu)先級最低的空閑任務,這時,每個時鐘節(jié)拍到達時進行任務就緒態(tài)檢查和調度管理。
μC/OS-Ⅱ下的任務可以有5種狀態(tài),即就緒態(tài)、執(zhí)行態(tài)、被中斷態(tài)、等待態(tài)和休眠態(tài)。就緒態(tài)表示該任務已經準備好,隨時可以執(zhí)行,但由于其優(yōu)先級比正在運行的任務優(yōu)先級低,暫時得不到CPU執(zhí)行權,而在就緒列表中排隊;執(zhí)行態(tài)表示該任務獲得了CPU執(zhí)行權,正在運行;被中斷態(tài)表示該任務被中斷服務程序中斷了;等待態(tài)表示該任務在等待運行(一般地,等待某一事件的發(fā)生或超時信號,處于等待態(tài)的任務位于等待列表隊列中,與就緒態(tài)任務的區(qū)別在于,即使獲得了CPU使用權,等待態(tài)任務也不能得到執(zhí)行);休眠態(tài)專指一個任務被刪除后的狀態(tài)(任務不能被從內存中刪除,只是從任務列表中刪除,仍然位于內存中,這種任務狀態(tài)稱為休眠態(tài)),可以調用創(chuàng)建任務函數,使任務轉到就緒態(tài)。任務中可以調用各種函數,被任務調用的函數是通常意義上的函數,但是,在μC/OS-Ⅱ中,要求這些被調用函數為可重入函數。所謂的可重入函數,是指只使用局部變量而不使用全局變量的函數,這樣被多個任務調用時,每個任務下可重入函數都有自己獨立的數據,不會造成數據變量使用的混亂。如果一個函數使用了全局變量,而這個全局變量被某個任務修改后,后繼調用這個函數的任務都將使用被修改了的全局變量,從而得到意想不到的結果。所以,在μC/OS-Ⅱ下編寫的函數都應該是可重入函數,即不使用全局變量、只使用局部變量的函數。4.1.1任務控制塊
每個任務都與一個任務控制塊結構體變量相關聯(lián),用于保存該任務的工作狀態(tài)。任務控制塊結構體類型在ucos_ii.h中定義,代碼如下:上述代碼中預編譯常量均在os_cfg.h中定義(實際上,所有的預編譯常量均在os_cfg.h中定義,通過修改這些常量的值為0,可以大幅度地裁剪μC/OS-Ⅱ代碼長度)。第2行OSTCBStkPtr表示指向當前任務的堆棧指針,每個任務都具有獨立的堆棧空間,且空間大小隨意指定。第4~10行表示如果使用OSTaskCreateExt函數創(chuàng)建任務,其任務控制塊中需要有第5~9行的成員,即OSTCBExtPtr指向用戶定義的數據結構,用于擴展任務控制塊數據;OSTCBStkBottom是指向該任務堆棧棧底的指針;OSTCBStkSize為堆棧大??;
OSTCBOpt為選項,一般只能取四個值或其組合,即OS_TASK_OPT_NONE(在ucos_ii.h中宏定義為0)、OS_TASK_OPT_STK_CHK(值為1)、OS_TASK_OPT_STK_
CLR(值為2)或OS_TASK_OPT_SAVE_FP(值為4),其中,OS_TASK_OPT_STK_CHK表示使能堆棧檢查,OS_
TASK_OPT_STK_CLR表示創(chuàng)建堆棧時將堆??臻g清為0,這二者常組合在一起使用;OSTCBId表示任務ID號,取值為0~65535,用戶可以使用這個ID號作為數組索引,在μC/OS-Ⅱ內核中并沒有意義。第12~13行為任務控制塊結構體指針,OSTCBNext指向下一個任務控制塊,OSTCBPrev指向前一個任務控制塊,這兩個指針把所有任務的任務控制塊連成一個雙向鏈表,每個任務在創(chuàng)建時,將其任務控制塊插入鏈表中。第16行OSTCBEventPtr為指向事件控制塊的指針;第20行為指向多事件控制塊的指針,多事件請求處理機制是μC/OS-ⅡV2.86新添加的特性。第24行表示指向傳遞給任務的消息或消息隊列的指針。第29行為指向事件標志節(jié)點的指針;第31行為事件標志就緒狀態(tài)變量。第34行OSTCBDly表示任務的延時節(jié)拍數;第35行OSTCBStat保存任務狀態(tài);第36行OSTCBStatPend保存任務掛起狀態(tài);第37行OSTCBPrio為任務優(yōu)先級,0級最高。第39~47行與任務就緒表有關,OSTCBX是優(yōu)先級分組的位索引,OSTCBY是優(yōu)先級就緒表的索引,OSTCBBitX是訪問就緒表位的位屏蔽,OSTCBBitY是訪問優(yōu)先級分組位的位屏蔽。第41行判斷OS_LOWEST_PRIO是否小于等于63,如果是的話,OSTCBBitX和OSTCBBitY均為8位無符號整型變量,否則為16位無符號整型變量。
第50行表示任務是否需要刪除自身。第53~59行為5個任務調度變量,分別記錄任務切換次數、任務執(zhí)行總時鐘周期、任務循環(huán)計數、任務堆棧首地址和堆棧使用量等調試信息。第62行為任務名稱,主要用作調試信息。在第4.2節(jié)的實例中,可以單步執(zhí)行查看每個任務的任務控制塊內容,在調試模式下,通過菜單“View|Locals”查看。4.1.2事件控制塊
事件控制塊結構體用于記錄任務間通信的信息,該結構體類型將在第五章中使用,其在ucos_ii.h中的定義如下:上述代碼第3行OSEventType表示事件類型,在ucos_ii.h中定義的事件類型有7種,即
#defineOS_EVENT_TYPE_UNUSED 0u
#defineOS_EVENT_TYPE_MBOX 1u
#defineOS_EVENT_TYPE_Q 2u
#defineOS_EVENT_TYPE_SEM 3u
#defineOS_EVENT_TYPE_MUTEX 4u
#defineOS_EVENT_TYPE_FLAG 5u
#defineOS_TMR_TYPE
100u分別表示空類型、郵箱、隊列、信號量、互斥量、標志和定時器類型。第4行OSEventPtr為指向郵箱或隊列的指針。第5行OSEventCnt為信號量計數值,如果為其他事件類型則該成員不使用。第6~12行的OSEventGrp和OSEventTble分別為等待事件的任務分組和任務列表。第15行為事件名,一般用作調試。
在第5章實例ex5_1中可以查看事件控制塊變量的內容。
在ucos_ii.h中還定義了事件標志控制塊、消息郵箱數據結構、內存控制塊、互斥量數據結構、消息列隊數據結構、信號量數據結構、定時器數據結構等數據類型,在使用這些數據類型時再作介紹,這里不詳細說明了,讀者可直接參考ucos_ii.h文件。任務堆棧數據結構定義如下:
1#ifOS_TASK_CREATE_EXT_EN>0
2typedefstructos_stk_data{
3INT32UOSFree; /*Numberoffreebytesonthestack*/
4INT32UOSUsed;/*Numberofbytesusedonthestack*/
5}OS_STK_DATA;
6#endif
上述代碼第3行OSFree表示堆棧中沒有使用的字節(jié)數;第4行表示堆棧中已使用的字節(jié)數。4.1.3就緒表
μC/OS-Ⅱ是多任務操作系統(tǒng),系統(tǒng)的核心功能是任務調度,即當一個任務發(fā)生切換時,μC/OS-Ⅱ需要在眾多已經就緒的任務中找到優(yōu)先級最高的任務。為了實現(xiàn)快速查找,J.J.Labrosse使用查表的方法。他設計了一個表,表中的元素為位,可以根據任務的優(yōu)先級將就緒任務填入表格的某位,同樣,由表格中的一些位可直接算得任務的優(yōu)先級。這樣,任務一旦就緒,其表格中相應的某位就按既定算法置位;任務調度時,根據表格中所有已置位的位,直接算出優(yōu)先級最高的就緒任務。設ptcb為某任務的任務控制塊變量,則使用以下語句將就緒任務填入就緒表中,這里的OSRdyGrp和OSRdyTbl即為Labrosse設計的表。
OSRdyGrp|=ptcb->OSTCBBitY; /*No,Makeready*/
OSRdyTbl[ptcb->OSTCBY]|=ptcb->OSTCBBitX;
而OSTCBBitY和OSTCBBitX由以下語句算出(位于os_core.c中第1960行):
結合圖4-1來理解任務就緒表的賦值操作。圖4-1中HPT表示最高優(yōu)先級任務,LPT表示最低優(yōu)先級任務,HPT(0)表示0為最高優(yōu)先級任務。OSRdyGrp和OSRdyTbl的大小依賴于OS_LOWEST_PRIO(位于os_cfg.h中,在ex4_1實例中修改為254)。圖4-1任務就緒表根據上述代碼和圖4-1,如果任務的優(yōu)先級為190(大于63),則OSTCBY=11,OSTCBX=14,OSTCBBitY=0x0800,OSTCBBitX=0x4000;如果該任務就緒了,且OSRdyGrp和OSRdyTbl都為0,則OSRdyGrp=0x0800,OSRdyTbl[11]為0x4000。在這個基礎上,另一個優(yōu)先級為28的任務就緒了,則它的OSTCBY=1,OSTCBX=12,OSTCBBitY=0x0002,OSTCBBitX=0x1000。此時任務就緒表的OSRdyGrp=0x0802,OSRdyTbl[1]=0x1000,OSRdyTbl[11]=0x4000。然后,優(yōu)先級為0x31的任務也就緒了,且上述兩個任務還沒有進入執(zhí)行狀態(tài),可以算得OSRdyGrp=0x0802,OSRdyTbl[1]=0x9000,OSRdyTbl[11]=0x4000,如圖4-2所示。圖4-2表格中的空格均為0。圖4-2三個任務的就緒表從圖4-2及上述推算過程知,有幾個任務就緒,OSRdyTbl中就有多少個1;如果OSRdyTbl中的某一行至少有一個1,則OSRdyGrp中對應的位就為1。
由上述過程,可以依據一個任務的優(yōu)先級得到它在就緒表中的位置。相反地,可以由就緒表的位,直接算得就緒表中的最高優(yōu)先級的任務的優(yōu)先級號。
假設就緒表如圖4-2所示(這里只有三個就緒任務,讀者可以自己演算更復雜的),在os_core.c中定義常量數組OSUnMapTbl如下:1INT8UconstOSUnMapTbl[256]={
20,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, /*0x00to0x0F*/
34,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, /*0x10to0x1F*/
45,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, /*0x20to0x2F*/
54,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, /*0x30to0x3F*/
66,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, /*0x40to0x4F*/
74,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, /*0x50to0x5F*/
85,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, /*0x60to0x6F*/
94,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, /*0x70to0x7F*/107,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, /*0x80to0x8F*/
114,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, /*0x90to0x9F*/
125,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, /*0xA0to0xAF*/
134,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, /*0xB0to0xBF*/
146,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, /*0xC0to0xCF*/
154,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, /*0xD0to0xDF*/
165,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, /*0xE0to0xEF*/
174,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 /*0xF0to0xFF*/
18};
由圖4-2推算就緒任務的最高優(yōu)先級號的算法(來自os_core.c)為按上述代碼和圖4-2易推算得,y=1,*ptbl=0x9000,就緒任務中的最高優(yōu)先級為OSPrioHighRdy=16+4+8=28。μC/OS-Ⅱ最多支持255個優(yōu)先級,使用查表方法速度很快,占用RAM空間也不多,而最新的μC/OS-Ⅲ支持無限多個優(yōu)先級,顯然不能用查表方法,作者可能使用了一種基于鏈表的新算法。4.1.4空閑任務和統(tǒng)計任務
在os_cfg.h中定義了OS_LOWEST_PRIO后,系統(tǒng)將自動把該優(yōu)先級分配給空閑任務(即沒有用戶任務執(zhí)行的狀態(tài)下運行的任務,位于os_core.c中),其代碼如下:上述代碼是一個簡單的死循環(huán)體,空閑記數器OSIdleCtr不斷累加(第12行)。用戶可以添加自定義代碼(添加到OSTaskIdleHook鉤子函數中),使進入空閑狀態(tài)的任務點亮LED燈提示或使CPU工作于省電模式。
統(tǒng)計任務(位于os_core.c中)的代碼如下:由上述代碼可知,統(tǒng)計任務開始工作(即進入死循環(huán))后,要計算CPU的使用率OSCPUUsage(第24行),然后進行任務堆棧的檢查,最后,延時0.1秒進入任務切換。用戶可以通過鉤子函數OSTaskStatHook插入自定義的代碼。統(tǒng)計任務需要一個初始化函數OSStatInit,這個函數需在調用OSInit后和進入多任務前調用。
μC/OS-Ⅱ代碼中有大量的預編譯指令代碼,這些預編譯常量一般在os_cfg.h中定義,用于對μC/OS-Ⅱ內核代碼進行裁剪。對于UP-Star實驗板來說,由于其具有32MB的RAM空間,無需進行裁剪。對于RAM空間較小的單片機系統(tǒng)板,則往往需要裁剪。4.1.5時鐘節(jié)拍
μC/OS-Ⅱ系統(tǒng)借助一個時鐘節(jié)拍實現(xiàn)任務的延時管理和超時調度,時鐘節(jié)拍由定時器中斷服務程序調用,必須在調用了OSStart后才能開啟時鐘節(jié)拍!
在后面的實例ex4_1中,使用S3C2410A的內部定時器4實現(xiàn)時鐘節(jié)拍功能,即在其中斷服務函數中調用OSTimeTick,完整代碼可參閱bsp.c文件,這里不再列出。時鐘節(jié)拍的任務調度均由匯編語言編寫,位于os_cpu_a.asm(或os_cpu_a.s)中,這里也不再羅列。
為了使時鐘節(jié)拍的頻率為OS_TICKS_PER_SEC(位于os_cfg.h中第51行)所宏定義的值,必須設置定時器4的中斷信號頻率為OS_TICKS_PER_SEC,一般為100Hz。
由上述內容可知,本小節(jié)內容與μC/OS-Ⅱ的移植關系密切。4.1.6μC/OS-Ⅱ初始化
將第4.2節(jié)的實例ex4_1的主程序代碼羅列如下:由上述代碼可知,μC/OS-Ⅱ系統(tǒng)的啟動分為三步,即調用OSInit初始化系統(tǒng)、創(chuàng)建任務(這里使用了OSTaskCreateExt)、調用OSStart啟動多任務。一般地,在第一個創(chuàng)建的任務代碼中添加創(chuàng)建其他任務的代碼,這個在主函數(main)中創(chuàng)建的任務稱為“引導”任務,而在其中創(chuàng)建的任務稱為“工作”任務。引導任務只用來創(chuàng)建一些工作任務,本身沒有太大意義;工作任務是用來完成特定功能的任務。
進入到os_core.c中可查得OSInit的代碼如下:上述代碼完成了μC/OS-Ⅱ系統(tǒng)的初始化,包括初始化全局變量、任務控制塊、事件控制塊、內存控制塊、創(chuàng)建統(tǒng)計任務、初始化堆棧、定時器管理任務等內容,讀者可通過單步調試工程ex4_1獲得更多的信息。其實,Labrosse先生完全可以把OSStatInit函數通過預編譯指令加入到OSInit中(第29行以后)。
在os_core.c中可查得OSStart函數的代碼如下:第3行OSRunning為真(OS_TRUE)時表示多任務工作開始了;如果為OS_FALSE,則表示系統(tǒng)還沒有工作,此時第4~8行查找最高優(yōu)先級的任務,然后開始多任務調度工作。在OSStartHighRdy中將OSRunning置為OS_TURE(即1)。
μC/OS-Ⅱ意義下的任務是一個無限循環(huán)的函數,即任務被創(chuàng)建時即相當于被“執(zhí)行”了,這里的“執(zhí)行”只是完成了任務的入棧操作,并沒有執(zhí)行任務代碼;當任務被“調用”時,即程序切換到該任務執(zhí)行時,相當于程序返回到該任務去執(zhí)行,即有一個出棧過程。任務中可以加入一些初始化代碼,但其主體代碼位于while(1)或for(;;)死循環(huán)中。如果只想讓任務執(zhí)行一次就退出,則需在死循環(huán)中加入OSTaskDel(OS_PRIO_SELF)語句。
本節(jié)將介紹第一章表1-4中一些函數的使用方法。首先建立一個工程ex4_1。4.2任務OS_TASK.C4.2.1工程ex4_1
在工程ex3_2的基礎上新建工程ex4_1,保存目錄為D:\ZYUCOSII\ex4_1,此時的工程ex4_1與ex3_2完全相同,只是工程文件名更改為ex4_1,如圖4-3所示。圖4-3工程ex4_1的最初版本在圖4-3的基礎上,需要修改的文件有app.c、appfun.c、app.h、includes.h、bsp.c、os_cfg.h等。其中,os_cfg.h中僅是把其第39行中的OS_LOWEST_PRIO宏定義值由63更改為254;includes.h文件中添加了一行“#include"math.h"”,用于計算數學函數;bsp.c文件中把函數myInitUART0中的串口0初始化波特率值設為115200bps,這個函數的代碼如下:
1//InitializeUART0
2voidmyInitUART0(void)
3{
4//SetGPH3:2asRXD0:TXD0
5GPHCON=0xA0;6
7//UBRDIV0=0x270,SetUART0Baudrate:4800bps,8-bit,1-bitstop
8//UBRDIV0=0x19,SetUART0Baudrate:115200bps,8-bit,1-bitstop
9UFCON0=0x0;
10UMCON0=0x0;
11ULCON0=0x03;
12UCON0=0x05;
13UBRDIV0=0x19;
14}
app.h文件中添加了一些任務(或函數)的原型定義,完整的代碼如下:
1/*FileName:app.h
2**Byzhnyong@21
3**@2009-4-4
4**CopyrightReserved
5*/
6
7#ifdefMY_APP_GLOBALS
8#defineMY_APP
9#else
10#defineMY_APPextern
11#endif上述代碼中,第42~45行宏定義了4個任務的優(yōu)先級,為5~8;第47行宏定義了AppTaskStart任務的堆棧大小;第48行宏定義了其他任務的堆棧大小。第34行N_TASKS表示用戶創(chuàng)建任務的個數,其ID號在第36~39行宏定義,堆棧在第50~54行定義,任務的原型在第65、67~69行聲明。
app.c和appfun.c的內容將在第4.2.2和第4.2.3節(jié)介紹。
工程ex4_1運行時,可以看到三個LED燈每隔1秒閃爍,同時,串口調試助手中顯示一些信息,如圖4-4和圖4-5所示。圖4-4工程ex4_1運行情況圖4-5串口調試助手顯示情況比較圖4-4和圖4-5可以看出,使用C-SPY顯示的系統(tǒng)堆棧信息和串口調試助手顯示的信息完全一致,工程ex4_1中共有7個任務,4個用戶創(chuàng)建任務,CPU利用率約1%,每秒任務切換約為42(圖4-5由于運行時間太短,顯示的切換統(tǒng)計數33不太準確,請讀者自己分析原因,并根據圖4-4推算準確任務切換數)。圖4-5中還顯示了當前μC/OS-Ⅱ的版本號為V2.86,并且顯示了30度角的正弦值。4.2.2主程序app.c
app.c的完整代碼如下:
1/*FileName:app.c
2**Byzhnyong@21
3**@2009-4-4
4**MainRoutine
5**CopyrightReserved
6*/
7
8#include"includes.h"
9
10voidmain(void)
11{基于μC/OS-Ⅱ的主函數main,首先調用OSInit進行系統(tǒng)初始化(第12行),然后調用OSTaskCreateExt創(chuàng)建一個用戶任務AppTaskStart(第13行),之后調用OSStart函數開始多任務調度(第22行)。
μC/OS-Ⅱ中有兩個創(chuàng)建任務的函數,即OSTaskCreate和OSTaskCreateExt,這兩個函數的原型位于ucos_ii.h中,如下所示:
OSTaskCreate有4個參數,依次傳遞任務名(函數名)、任務參數、任務堆棧頂地址、任務優(yōu)先級(第2~5行)。OSTaskCreateExt是OSTaskCreate的擴展,有9個參數,依次傳遞任務名、任務參數、任務堆棧頂地址、任務優(yōu)先級、任務ID號、任務堆棧底地址、任務堆棧大小、用戶自定義數據地址、指定是否允許堆棧檢查和清零等的選項值。
Labrosse建議用戶使用OSTaskCreateExt創(chuàng)建任務,這類任務可以用C-SPY調試器查看堆棧使用情況。例如,在文件app.c中的第13行,創(chuàng)建的任務名為AppTaskStart;任務參數為空;棧頂地址為AppTaskStartStk[TASK_START_STK_SIZE-1];優(yōu)先級為AppTaskStartPrio;ID號為AppTaskStartID;棧底地址為AppTaskStartStk[0];棧大小為TASK_START_STK_SIZE;用戶數據為空;選項為OS_TASK_OPT_STK_CHK|OS_TASK_
OPT_STK_CLR,表示任務堆棧檢查和清零。4.2.3任務程序appfun.c
文件appfun.c的完整代碼如下:
1/*FileName:appfun.c
2**Byzhnyong@21
3**@2009-4-4
4**CopyrightReserved
5*/
6
7#defineMY_APP_GLOBALS
8#include"includes.h"
9
上述代碼第10~60行為LED相關的代碼,只需對第41~60行的代碼作一說明即可。參考第一章圖1-31,三個LED燈接在GPC5~7引腳上,第44行讀取這三個引腳的值;第48行為讀出值與0x0020異或,這樣,只有LED1燈的狀態(tài)翻轉,其他兩個燈的狀態(tài)不變,這表現(xiàn)為LED1會閃爍;同理,第51、54和57行分別實現(xiàn)LED2、LED3以及LED1~3的狀態(tài)變化,即實現(xiàn)LED燈的閃爍。
第61~69行為開定時器4中斷。第70~113行為串口0相關的函數,實現(xiàn)了串口0的字節(jié)讀/寫以及字符串的輸出功能。第117~156行為AppTaskStart任務的代碼。第129行調用OSVersion函數獲得μC/OS-Ⅱ的版本號,這里返回的值為286;第130行將os_version變量的值格式化賦給字符串sOsVer;第131行通過串口0輸出;第134~136行計算30度角的正弦值,并通過串口輸出。
第138~140行開定時器4。第138行為關中斷操作,這樣第139行代碼執(zhí)行過程中不受干擾;第140行恢復CPU的狀態(tài)(注意,這里只是恢復,并沒有開中斷。如果中斷原來是關閉的,則第140行執(zhí)行完后,中斷仍然是關閉的)。
第142行調用OSStatInit初始化統(tǒng)計任務用到的一些全局量。第144行調用自定義函數TaskStartCreateTasks創(chuàng)建一些任務,后面會介紹。
第146行將當前任務命名為AppTaskStart。
第148~155為死循環(huán)體。第150行將CPU利用率和任務切換數格式化輸出到字符串s;第151行將s通過串口輸出;第153行清除任務切換數;第154行延時3秒。
第157~190行借助OSTaskCreateExt創(chuàng)建了三個任務。與第4.2.2節(jié)app.c中第20行不同的地方是,這里的第168、178、188行均使用一個自定義結構體類型變量,用于傳遞用戶數據,這里的TaskUserData變量在app.h中定義,有任務名、任務運行次數、任務單次運行時間等三個成員。第191~256行為三個任務的函數體,這里只解釋第191~224行的任務1。第200行為任務1命名,OSTaskNameSet函數有三個參數,分別為任務優(yōu)先級(OS_PRIO_SELF表示任務本身)、任務名字符串和調用成功與否的提示信息。第205行調用OSTaskStkChk函數檢查任務堆棧,OSTaskStkChk有兩個參數,即任務的優(yōu)先級和指向記錄堆棧信息的結構體變量指針,該結構體類型OS_STK_DATA參見第4.1.2節(jié)。第209~215行將堆棧使用情況通過串口0輸出。第218行調用OSTimeGet獲得系統(tǒng)時鐘節(jié)拍的總計數值。對比第222、242和254行,可知任務1、2、3的延時分別為10秒、5秒和1秒,因此它們的執(zhí)行次數的比值為1:2:10,在圖4-5中向下拉動窗口滾動條會觀察到這種情況。第258~263行定義了一個函數DispTaskStat,輸入參數為任務的優(yōu)先級,該函數輸出自定義結構體數組變量TaskUserData的內容。
綜上所述,AppTaskStart任務的功能為:當第一次執(zhí)行時,輸出μC/OS-Ⅱ版本號,計算并輸出sin(30°)的值;然后,打開定時器4中斷,初始化統(tǒng)計任務全局變量,創(chuàng)建三個任務,設置任務名為AppTaskStart;進入任務循環(huán)體后,每隔3秒輸出任務數、CPU利用率和任務每秒切換次數。AppTask_1任務的功能為:第一次執(zhí)行時,設置任務名為AppTask_1;進入任務循環(huán)體后,每隔10秒,輸出三個用戶任務使用堆棧的情況以及總的時鐘節(jié)拍計數。
AppTask_2任務的功能為:第一次執(zhí)行時,初始化TaskUserData的成員TaskCtr,將任務命名為AppTask_2;進入任務循環(huán)體后,每隔5秒調用函數DispTaskStat顯示各個任務的用戶信息,即任務名和執(zhí)行次數。AppTask_3任務的功能為:第一次執(zhí)行時,關閉所有LED燈,將任務命名為AppTask_3;進入任務循環(huán)體后,每隔1秒,三個LED燈閃爍一次。
本小節(jié)中使用的OSVersion、OSTaskNameSet、OSTimeDly、OSTaskCreateExt、OSTimeDlyHMSM等函數的詳細說明可以參考“μC/OS-ⅡReferenceManual”手冊(位于第1.1節(jié)中的Micrium-uCOS-Ⅱ-V286.ZIP壓縮包中)。這個手冊中包含了幾乎所有μC/OS-Ⅱ的常用函數。4.2.4工程ex4_2
第一章表1-4中函數OSTaskCreate在第三章已用到了,工程ex4_1中沒有出現(xiàn)的函數有OSTaskDel、OSTaskDelReq、OSTaskSuspend、OSTaskResume、OSTaskNameGet、OSTaskQuery和OSTaskChangePrio。為了介紹這些函數的使用方法,在工程ex4_1的基礎上,新建工程ex4_2,保存在目錄D:\ZYUCOSII\ex4_2中(新建的工程與ex4_1完全相同,只是工程文件名改為ex4_2)。然后,僅修改appfun.c文件的AppTask_1和AppTask_3函數即得工程ex4_2。
任務AppTask_1和AppTask_3的內容如下:
1voidAppTask_1(void*pdata)
2{
3OS_STK_DATAstkData;
4INT8Uerr;
5INT8Ui;
6INT8Us[80];
7INT32UstkSize;修改的內容從第36行開始,判斷時鐘節(jié)拍計數值是否大于4000而小于6000,即經過40秒而不超過60秒時,第38~39行判斷優(yōu)先級為AppTask_3_Prio的任務(即任務3)是否存在,如果存在,則第41行調用OSTaskDelReq函數請求任務3刪除自己。這里的OSTaskDelReq函數只有一個參數,即任務優(yōu)先級,該函數向將被刪除的任務發(fā)出刪除請求,它本身不刪除任務。在第107行任務3判斷有沒有任務請求它刪除它自身,如果有,則第109行調用OSTaskDel刪除任務3。當tickCur>4000時,即經過40秒后,任務3將被刪除,這里,三個LED燈不再閃爍??山Y合串口調試助手觀察時間的變化。
從第45行開始,將判斷時鐘節(jié)拍是否大于6000而小于8000,如果是,則進一步判斷任務3是否存在(第47~48行),如果不存在,則調用OSTaskCreateExt重新創(chuàng)建任務3。也就是說,到60秒的時候,三個LED燈間隔了20秒后重新開始閃爍了。
第62行,即時鐘節(jié)拍到了8000次以上而不超過10000次時,將調用OSTaskSuspend掛起任務3。OSTaskSuspend只有一個參數,即任務的優(yōu)先級,與OSTaskResume的作用相反,被掛起的任務只能調用OSTaskResume恢復運行。因此,到80秒的時候,三個LED燈又不再閃爍了。間隔20秒后,到了第67~70行,調用OSTaskResume恢復任務3,這時三個LED燈繼續(xù)開始閃爍了。
然后,到了第72行,即到
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 特許金融分析師考試科目安排試題及答案
- CFA知識體系全貌與試題及答案
- 投資者情緒對市場的影響試題及答案
- 2024CFA考試全景回顧試題及答案
- 中職商務英語專業(yè)口語教學問題及對策研究
- 高速公路交通安全培訓
- 給學校設計警示牌
- 2025年寧夏銀川一中高考英語一模試卷
- 骨科頸椎護理查房
- CFA考試中應注意的細節(jié)試題及答案
- 新質生產力:學術研究與前沿探索
- 5.1 人民代表大會:我國的國家權力機關 課件高中政治統(tǒng)編版必修三政治與法治
- 邢臺2025年河北邢臺市高層次人才引進1025人筆試歷年參考題庫附帶答案詳解
- 2025年統(tǒng)計學 1試題及答案
- 2025年起重工(技師)職業(yè)技能鑒定理論考試題庫(含答案)
- 中職《基礎化學》對口高考備考試題(附答案)
- 房屋建筑學2025年新技術應用
- 傷口感染患者的護理常規(guī)
- 2025年電梯修理T證試題(附答案)
- 《油庫安全管理培訓》課件
- 第1課認識機器人(課件)小學信息技術六年級同步教學
評論
0/150
提交評論