![第四講ucOSII內核結構-03_第1頁](http://file4.renrendoc.com/view/a8f13d981fb4fb577ca183ee24d6b5bd/a8f13d981fb4fb577ca183ee24d6b5bd1.gif)
![第四講ucOSII內核結構-03_第2頁](http://file4.renrendoc.com/view/a8f13d981fb4fb577ca183ee24d6b5bd/a8f13d981fb4fb577ca183ee24d6b5bd2.gif)
![第四講ucOSII內核結構-03_第3頁](http://file4.renrendoc.com/view/a8f13d981fb4fb577ca183ee24d6b5bd/a8f13d981fb4fb577ca183ee24d6b5bd3.gif)
![第四講ucOSII內核結構-03_第4頁](http://file4.renrendoc.com/view/a8f13d981fb4fb577ca183ee24d6b5bd/a8f13d981fb4fb577ca183ee24d6b5bd4.gif)
![第四講ucOSII內核結構-03_第5頁](http://file4.renrendoc.com/view/a8f13d981fb4fb577ca183ee24d6b5bd/a8f13d981fb4fb577ca183ee24d6b5bd5.gif)
版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
ucOS-II內核結構臨界段(CriticalSections)
μC/OS-Ⅱ為了處理臨界段代碼需要關中斷,處理完后再開中斷。μC/OS-Ⅱ定義兩個宏(macros)OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()來關中斷和開中斷,以便避開不同C編譯器廠商選擇不同的方法來處理關中斷和開中斷。這兩個宏的定義取決于所用的微處理器,在文件OS_CPU.H中可以找到相應宏定義(每種微處理器都有自己的OS_CPU.H文件)。任務
一個任務通常是一個無限的循環(huán),而且一個任務的返回參數(shù)必須定義成void。任務完成以后,任務可以調用OSTaskDel()自我刪除,μC/OS-Ⅱ不再理會這個任務,任務的代碼也不會再運行。
一個無限循環(huán)任務的程序voidYourTask(void*pdata) (1){for(;;){ (2)/*用戶代碼*/
調用uC/OS-II的某種系統(tǒng)服務:
OSMboxPend();/任務進入等待狀態(tài)
OSQPend();/任務進入等待狀態(tài)
OSSemPend();/任務進入等待狀態(tài)
OSTaskDel(OS_PRIO_SELF);/任務完成后自我刪除
OSTaskSuspend(OS_PRIO_SELF);/任務掛起等待
OSTimeDly();/延遲一段時間
OSTimeDlyHMSM();/延遲一段時間/*用戶代碼*/}}任務控制塊(TaskControlBlocks,OS_TCBs)
任務一旦建立,任務控制塊OS_TCBs將被賦值。任務控制塊是一個數(shù)據(jù)結構,全部駐留在RAM中。當任務的CPU使用權被剝奪時,μC/OS-Ⅱ用它來保存該任務的狀態(tài)。當任務重新得到CPU使用權時,任務控制塊能確保任務從當時被中斷的那一點開始繼續(xù)向下執(zhí)行。任務建立的時候,OS_TCBs被初始化。μC/OS-II任務控制塊程序
typedefstructos_tcb{OS_STK*OSTCBStkPtr;/
指向當前任務棧頂?shù)闹羔?,是OS_TCB數(shù)據(jù)結構中唯一一個能用匯編語言來處置的變量(在任務切換段的代碼Context-switchingcode之中)#ifOS_TASK_CREATE_EXT_ENvoid*OSTCBExtPtr;/指向用戶定義的任務控制塊擴展,只在函數(shù)OstaskCreateExt()中使用,故使用時要將OS_TASK_CREAT_EN設為1,以允許建立任務函數(shù)的擴展
OS_STK*OSTCBStkBottom;/指向任務棧底的指針,通過OSTaskCreateExt()函數(shù)建立任務時才能實現(xiàn)OSTaskStkChk()功能,要求是將OS_TASK_CREATE_EXT_EN設為1。INT32UOSTCBStkSize;/存放棧中可容納的指針數(shù)目而不是用字節(jié)(Byte)表示的棧容量總數(shù),在函數(shù)OSStakChk()中調用,同樣要將OS_TASK_CREAT_EXT_EN設為1。
INT16UOSTCBOpt;/把OS_TASK_OTP_STK_CHK,OS_TASK_OPT_STK_CLR和OS_TASK_OPT_SAVE_FP三個“選擇項”傳給OSTaskCreateExt()。INT16UOSTCBId;/存儲任務的識別碼,現(xiàn)在暫時沒有使用#endif
/用于任務控制塊OS_TCBs的雙重鏈接,該鏈表在時鐘節(jié)拍函數(shù)OSTimeTick()中使用,用于刷新各個任務的任務延遲變量.OSTCBDly,每個任務的任務控制塊OS_TCB在任務建立的時候被鏈接到鏈表中,在任務刪除的時候從鏈表中被刪除。雙重連接的鏈表使得任一成員都能被快速插入或刪除。structos_tcb*OSTCBNext;structos_tcb*OSTCBPrev;#if(OS_Q_EN&&(OS_MAX_QS>=2))||OS_MBOX_EN||OS_SEM_ENOS_EVENT*OSTCBEventPtr;/指向事件控制塊的指針#endifμC/OS-II任務控制塊程序
#if(OS_Q_EN&&(OS_MAX_QS>=2))||OS_MBOX_ENvoid*OSTCBMsg;/指向傳給任務的消息的指針
#endif
INT16UOSTCBDly;/當需要把任務延時若干時鐘節(jié)拍時要用到這個變量,或者需要把任務掛起一段時間以等待某事件的發(fā)生,這種等待是有超時限制的。如果這個變量為0,表示任務不延時,或者表示等待事件發(fā)生的時間沒有限制。
INT8UOSTCBStat;/任務的狀態(tài)字,當.OSTCBStat為0,任務進入就緒態(tài)。
INT8UOSTCBPrio;/任務優(yōu)先級,高優(yōu)先級任務的.OSTCBPrio值小。
INT8UOSTCBX;INT8UOSTCBY;INT8UOSTCBBitX;INT8UOSTCBBitY;/以上四個變量用于加速任務進入就緒態(tài)的過程或進入等待事件發(fā)生狀態(tài)的過程(避免在運行中去計算這些值)。這些值是在任務建立時算好的,或者是在改變任務優(yōu)先級時算出的。
#ifOS_TASK_DEL_ENBOOLEANOSTCBDelReq;/一個布爾量,用于表示該任務是否需要刪除#endif}OS_TCB;.OSTCBX,.OSTCBY,.OSTCBBitX和.OSTCBBitY的計算任務控制塊OS_TCB中幾個成員的算法程序OSTCBY=priority>>3;OSTCBBitY=OSMapTbl[priority>>3];OSTCBX=priority&0x07;OSTCBBitX=OSMapTbl[priority&0x07];應用程序中可以有的最多任務數(shù)(OS_MAX_TASKS)是在文件OS_CFG.H中定義的。這個最多任務數(shù)也是μC/OS-Ⅱ分配給用戶程序的最多任務控制塊OS_TCBs的數(shù)目。將OS_MAX_TASKS的數(shù)目設置為用戶應用程序實際需要的任務數(shù)可以減小RAM的需求量。所有的任務控制塊OS_TCBs都是放在任務控制塊列表數(shù)組OSTCBTbl[]中的。請注意,μC/OS-Ⅱ分配給系統(tǒng)任務OS_N_SYS_TASKS若干個任務控制塊,見文件μC/OS-Ⅱ.H,供其內部使用。目前,一個用于空閑任務,另一個用于任務統(tǒng)計(如果OS_TASK_STAT_EN是設為1的)??杖蝿真湵?/p>
在μC/OS-Ⅱ初始化的時候,所有任務控制塊OS_TCBs被鏈接成單向空任務鏈表。當任務一旦建立,空任務控制塊指針OSTCBFreeList指向的任務控制塊便賦給了該任務,然后OSTCBFreeList的值調整為指向下個鏈表中下一個空的任務控制塊。一旦任務被刪除,任務控制塊就被還給空任務鏈表。就緒表(ReadyList)μC/OS-Ⅱ初始化的時候,最低優(yōu)先級OS_LOWEST_PRIO總是被賦給空閑任務idletask。每個任務的就緒態(tài)標志都放入就緒表中的,就緒表中有兩個變量OSRedyGrp和OSRdyTbl[]。在OSRdyGrp中,任務按優(yōu)先級分組,8個任務為一組。OSRdyGrp中的每一位表示8組任務中每一組中是否有進入就緒態(tài)的任務。任務進入就緒態(tài)時,就緒表OSRdyTbl[]中的相應元素的相應位也置位。就緒表OSRdyTbl[]數(shù)組的大小取決于OS_LOWEST_PRIO(見文件OS_CFG.H)。
OSRdyGrp和OSRdyTbl[]之間的關系圖
任務進入就緒態(tài)程序
OSRdyGrp|=OSMapTbl[prio>>3];OSRdyTbl[prio>>3]|=OSMapTbl[prio&0x07];OSMapTbl[]的值IndexBitMask(Binary)000000001100000010200000100300001000400010000500100000601000000710000000任務優(yōu)先級的低三位用于確定任務在總就緒表OSRdyTbl[]中的所在位。接下去的三位用于確定是在OSRdyGrp[]數(shù)組的第幾個元素。例如:prio=00110001(prio=49)從就緒表中刪除一個任務程序if((OSRdyTbl[prio>>3]&=~OSMapTbl[prio&0x07])==0) OSRdyGrp&=~OSMapTbl[prio>>3];
將就緒任務表數(shù)組OSRdyTbl[]中相應元素的相應位清零,而對于OSRdyGrp,只有當被刪除任務所在任務組中全組任務一個都沒有進入就緒態(tài)時,才將相應位清零。也就是說OSRdyTbl[prio>>3]所有的位都是零時,OSRdyGrp的相應位才清零。
找到進入就緒態(tài)的優(yōu)先級最高的任務
不需要從OSRdyTbl[0]開始掃描整個就緒任務表,只需要查另外一張表,即優(yōu)先級判定表OSUnMapTbl([256])(見文件OS_CORE.C)。OSRdyTbl[]中每個字節(jié)的8位代表這一組的8個任務哪些進入就緒態(tài)了,低位的優(yōu)先級高于高位。利用這個字節(jié)為下標來查OSUnMapTbl這張表,返回的字節(jié)就是該組任務中就緒態(tài)任務中優(yōu)先級最高的那個任務所在的位置。這個返回值在0到7之間。找出進入就緒態(tài)的優(yōu)先級最高的任務程序y=OSUnMapTbl[OSRdyGrp];x=OSUnMapTbl[OSRdyTbl[y]];prio=(y<<3)+x;例如,如果OSRdyGrp的值為二進制00001010,查OSUnMapTbl[OSRdyGrp]得到的值是1,它相應于OSRdyGrp中的第1位bit1(假設最右邊的一位是第0位bit0)。類似地,如果OSRdyTbl[1]的值是二進制00010100,則OSUnMapTbl[OSRdyTbl[1]]的值是2,即第2位。于是任務的優(yōu)先級Prio就等于10(1*8+2)。
INT8UconstOSUnMapTbl[]={0,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x00to0x0F*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x10to0x1F*/5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x20to0x2F*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x30to0x3F*/6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x40to0x4F*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x50to0x5F*/5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x60to0x6F*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x70to0x7F*/7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x80to0x8F*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x90to0x9F*/5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0xA0to0xAF*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0xB0to0xBF*/6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0xC0to0xCF*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0xD0to0xDF*/5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0xE0to0xEF*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0/*0xF0to0xFF*/};OSUnMapTbl[]任務調度(TaskScheduling)
μC/OS-Ⅱ總是運行進入就緒態(tài)任務中優(yōu)先級最高的那一個。確定哪個任務優(yōu)先級最高,下面該哪個任務運行了,這個工作是由調度器(Scheduler)完成的。任務級的調度是由函數(shù)OSSched()完成的。中斷級的調度是由另一個函數(shù)OSIntExt()完成的,這個函數(shù)將在以后描述。任務調度器(theTaskScheduler)程序
voidOSSched(void){ INT8Uy;
OS_ENTER_CRITICAL(); if((OSLockNesting|OSIntNesting)==0){(1) /判斷是否在中斷服務子程序中調用OSSched(),此時中斷嵌套層數(shù)OSIntNesting>0,或者由于用戶至少調用了一次給任務調度上鎖函數(shù)OSSchedLock(),使OSLockNesting>0 y=OSUnMapTbl[OSRdyGrp];(2)/找出那個進入就緒態(tài)且優(yōu)先級最高的任務
OSPrioHighRdy=(INT8U)((y<<3)+OSUnMapTbl[OSRdyTbl[y]]);(2)if(OSPrioHighRdy!=OSPrioCur){(3)/檢驗這個優(yōu)先級最高的任務是不是當前正在運行的任務,以此來避免不必要的任務調度OSTCBHighRdy=OSTCBPrioTbl[OSPrioHighRdy];(4)/指向優(yōu)先級最高的那個任務控制塊OS_TCBOSCtxSwCtr++;(5)/統(tǒng)計計數(shù)器OSCtxSwCtr加1,以跟蹤任務切換次數(shù)
OS_TASK_SW();(6)/宏調用OS_TASK_SW()來完成任務切換}}OS_EXIT_CRITICAL();}任務切換由以下兩步完成,將被掛起任務的微處理器寄存器推入堆棧,然后將較高優(yōu)先級的任務的寄存器值從棧中恢復到寄存器中。μC/OS-Ⅱ運行就緒態(tài)的任務所要做的一切,只是恢復所有的CPU寄存器并運行中斷返回指令。為了做任務切換,運行OS_TASK_SW(),人為模仿了一次中斷。OSSched()的所有代碼都屬臨界段代碼。在尋找進入就緒態(tài)的優(yōu)先級最高的任務過程中,為防止中斷服務子程序把一個或幾個任務的就緒位置位,中斷是被關掉的。給調度器上鎖和開鎖
(LockingandUnLockingtheScheduler)
給調度器上鎖函數(shù)OSSchedlock()用于禁止任務調度,直到任務完成后調用給調度器開鎖函數(shù)OSSchedUnlock()為止,OSSchedlock()和OSSchedUnlock()必須成對使用。函數(shù)OSSchedLock()和OSSchedUnlock()的使用要非常謹慎,因為它們影響μC/OS-Ⅱ對任務的正常管理。
調用OSSchedLock()以后,用戶的應用程序不得使用任何能將現(xiàn)行任務掛起的系統(tǒng)調用。也就是說,用戶程序不得調用OSMboxPend()、OSQPend()、OSSemPend()、OSTaskSuspend(OS_PR1O_SELF)、OSTimeDly()或OSTimeDlyHMSM(),直到OSLockNesting回零為止。因為調度器上了鎖,用戶就鎖住了系統(tǒng),任何其它任務都不能運行。
給調度器上鎖程序voidOSSchedLock(void){ if(OSRunning==TRUE){OS_ENTER_CRITICAL(); OSLockNesting++; /變量OSLockNesting跟蹤OSSchedLock()函數(shù)被調用的次數(shù),以允許嵌套的函數(shù)包含臨界段代碼,這段代碼其它任務不得干預。μC/OS-Ⅱ允許嵌套深度達255層,當OSLockNesting等于零時,調度重新得到允許。
OS_EXIT_CRITICAL();}}給調度器開鎖程序voidOSSchedUnlock(void){ if(OSRunning==TRUE){OS_ENTER_CRITICAL();if(OSLockNesting>0){OSLockNesting--; if((OSLockNesting|OSIntNesting)==0){(1) OS_EXIT_CRITICAL(); OSSched();(2)/當OSLockNesting減到零的時候,OSSchedUnlock()調用OSSched} else{OS_EXIT_CRITICAL();}} else{OS_EXIT_CRITICAL();}}}空閑任務(IdleTask)
μC/OS-Ⅱ總是建立一個空閑任務,這個任務在沒有其它任務進入就緒態(tài)時投入運行。這個空閑任務[OSTaskIdle()]永遠設為最低優(yōu)先級,即OS_LOWEST_PRI0。空閑任務OSTaskIdle()什么也不做,只是在不停地給一個32位的名叫OSIdleCtr的計數(shù)器加1,統(tǒng)計任務使用這個計數(shù)器以確定現(xiàn)行應用軟件實際消耗的CPU時間。μC/OS-Ⅱ的空閑任務程序voidOSTaskIdle(void*pdata){ pdata=pdata; for(;;){OS_ENTER_CRITICAL();OSIdleCtr++;OS_EXIT_CRITICAL();}}空閑任務不可能被應用軟件刪除。
統(tǒng)計任務OSTaskStat()提供運行時間統(tǒng)計的任務。如果用戶將系統(tǒng)定義常數(shù)OS_TASK_STAT_EN(見文件OS_CFG.H)設為1,這個任務就會建立。一旦得到了允許,OSTaskStat()每秒鐘運行一次(見文件OS_CORE.C),計算當前的CPU利用率,用百分比表示,這個值放在一個有符號8位整數(shù)OSCPUsage中,精度是1個百分點。如果應用程序打算使用統(tǒng)計任務,用戶必須在初始化時建立一個唯一的任務,在這個任務中調用OSStatInit()(見文件OS_CORE.C),然后再建立應用程序中的其它任務。初始化統(tǒng)計任務程序voidmain(void){OSInit();/*初始化uC/OS-II(1)*//*安裝uC/OS-II的任務切換向量*//*創(chuàng)建用戶起始任務(為了方便討論,這里以TaskStart()作為起始任務)(2)*/OSStart();/*開始多任務調度(3)*/}初始化統(tǒng)計任務程序voidTaskStart(void*pdata){/*安裝并啟動uC/OS-II的時鐘節(jié)拍(4)*/OSStatInit();/*初始化統(tǒng)計任務(5)*//*創(chuàng)建用戶應用程序任務*/for(;;){/*這里是TaskStart()的代碼! */}}空閑任務的優(yōu)先級設為最低,統(tǒng)計任務的優(yōu)先級設為次低,啟動任務TaskStart()總是優(yōu)先級最高的任務。統(tǒng)計任務的初始化程序voidOSStatInit(void){OSTimeDly(2);OS_ENTER_CRITICAL();OSIdleCtr=0L;OS_EXIT_CRITICAL();OSTimeDly(OS_TICKS_PER_SEC);OS_ENTER_CRITICAL();OSIdleCtrMax=OSIdleCtr;OSStatRdy=TRUE;OS_EXIT_CRITICAL();}統(tǒng)計任務程序voidOSTaskStat(void*pdata){INT32Urun;INT8Susage;
pdata=pdata; while(OSStatRdy==FALSE){(1)/等待統(tǒng)計任務就緒
OSTimeDly(2*OS_TICKS_PER_SEC);} for(;;){OS_ENTER_CRITICAL(); OSIdleCtrRun=OSIdleCtr; run=OSIdleCtr; OSIdleCtr=0L; OS_EXIT_CRITICAL(); if(OSIdleCtrMax>0L){/CPU利用率 usage=(INT8S)(100L-100L*run/OSIdleCtrMax);(2) if(usage>100){OSCPUUsage=100;} elseif(usage<0){OSCPUUsage=0;} else{OSCPUUsage=usage;}} else{OSCPUUsage=0;} OSTaskStatHook();(3)/調用任務統(tǒng)計外界接入函數(shù)OSTaskStatHook(),這是一個用戶可定義的函數(shù),這個函數(shù)能使統(tǒng)計任務得到擴展。 OSTimeDly(OS_TICKS_PER_SEC);}}中斷處理
μC/OS中,中斷服務子程序要用匯編語言來寫。如果用戶使用的C語言編譯器支持在線匯編語言的話,可以直接將中斷服務子程序代碼放在C語言的程序文件中。用戶代碼應該將全部CPU寄存器推入當前任務棧。注意,有些微處理器,例如Motorola68020(及68020以上的微處理器),做中斷服務時使用另外的堆棧。μC/OS-II中的中斷服務子程序
用戶中斷服務子程序:保存全部CPU寄存器;(1)/將全部CPU寄存器推入當前任務棧調用OSIntEnter或OSIntNesting直接加1;(2)/μC/OS-Ⅱ需要知道用戶在做中斷服務
執(zhí)行用戶代碼做中斷服務;(3)調用OSIntExit();(4)/中斷服務子程序的終結,OSIntExit()將中斷嵌套層數(shù)計數(shù)器減1。當嵌套計數(shù)器減到零時,所有中斷,包括嵌套的中斷就都完成了,此時μC/OS-Ⅱ要判定有沒有優(yōu)先級較高的任務被中斷服務子程序(或任一嵌套的中斷)喚醒了。如果有優(yōu)先級高的任務進入了就緒態(tài),μC/OS-Ⅱ就返回到那個高優(yōu)先級的任務?;謴退蠧PU寄存器;(5)/OSIntExit()返回到調用點執(zhí)行中斷返回指令;(6)/如果調度被禁止了(OSIntNesting>0),μC/OS-Ⅱ將返回到被中斷了的任務。
在有些情況下,從OSIntEnter()返回時,會把中斷打開。此時,在調用OSIntEnter()之前要先清中斷源,否則,中斷將連續(xù)反復打入,用戶應用程序就會崩潰!注意
用戶中斷服務中做的事要盡可能地少,要把大部分工作留給任務去做。中斷服務子程序通知某任務去做事的手段是調用以下函數(shù)之一:OSMboxPost(),OSQPost(),OSQPostFront(),OSSemPost()。中斷發(fā)生并由上述函數(shù)發(fā)出消息時,接收消息的任務可能是,也可能不是掛起在郵箱、隊列或信號量上的任務。用戶中斷服務完成以后,要調用OSIntExit()。對被中斷了的任務說來,如果沒有高優(yōu)先級的任務被中斷服務子程序激活而進入就緒態(tài),OSIntExit()只占用很短的運行時間。如果中斷服務子程序使一個高優(yōu)先級的任務進入了就緒態(tài),則OSIntExit()將占用較長的運行時間,因為這時要做任務切換,新任務的寄存器內容要恢復并執(zhí)行中斷返回指令。進入中斷的函數(shù)OSIntEnter()代碼
voidOSIntEnter(void){ OS_ENTER_CRITICAL(); OSIntNesting++;/使中斷嵌套層數(shù)加1 OS_EXIT_CRITICAL();}退出中斷服務的函數(shù)OSIntExit()代碼
voidOSIntExit(void){ OS_ENTER_CRITICAL();(1) if((--OSIntNesting|OSLockNesting)==0) {(2)/使中斷嵌套層數(shù)減1
OSIntExitY=OSUnMapTbl[OSRdyGrp];(3)/OSRdyTbl[]所需的檢索值Y是保存在全局變量OSIntExitY中 OSPrioHighRdy=(INT8U)((OSIntExitY<<3)+ OSUnMapTbl[OSRdyTbl[OSIntExitY]]); if(OSPrioHighRdy!=OSPrioCur){ OSTCBHighRdy=OSTCBPrioTbl[OSPrioHighRdy]; OSCtxSwCtr++; OSIntCtxSw();(4)/OSIntExit()將調用OSIntCtxSw()做任務切換} } OS_EXIT_CRITICAL();}有的微處理器,像Motorola68HC11中斷發(fā)生時CPU寄存器是自動入棧的,一個任務和這個中斷服務子程序通訊的唯一方法是通過全程變量。時鐘節(jié)拍
μC/OS需要用戶提供周期性信號源,用于實現(xiàn)時間延時和確認超時。時鐘節(jié)拍率越高,系統(tǒng)的額外負荷就越重。時鐘節(jié)拍源可以是專門的硬件定時器,也可以是來自50/60Hz交流電源的信號。用戶必須在多任務系統(tǒng)啟動(調用OSStart())以后再開啟時鐘節(jié)拍器。即在調用OSStart()之后做的第一件事是初始化定時器中斷。通常,容易犯的錯誤是將允許時鐘節(jié)拍器中斷放在系統(tǒng)初始化函數(shù)OSInit()之后,在調用多任務系統(tǒng)啟動函數(shù)OSStart()之前。此時μC/OS-Ⅱ是處在一種不確定的狀態(tài)之中,用戶應用程序有可能會崩潰。時鐘節(jié)拍中斷服務子程序
μC/OS-Ⅱ中的時鐘節(jié)拍服務是通過在中斷服務子程序中調用OSTimeTick()實現(xiàn)的。這段代碼必須用匯編語言編寫,因為在C語言里不能直接處理CPU的寄存器。時鐘節(jié)拍中斷服務子程序的示意代碼
voidOSTickISR(void){ 保存處理器寄存器的值; 調用OSIntEnter()或是將OSIntNesting加1; 調用OSTimeTick();
調用OSIntExit(); 恢復處理器寄存器的值; 執(zhí)行中斷返回指令;}時鐘節(jié)拍函數(shù)OSTimeTick()的代碼
voidOSTimeTick(void){ OS_TCB*ptcb;
OSTimeTickHook();(1)/用戶定義的時鐘節(jié)拍外連函數(shù) ptcb=OSTCBList;(2)/OSTimTick()從OSTCBList開始,沿著OS_TCB鏈表順序執(zhí)行
while(ptcb->OSTCBPrio!=OS_IDLE_PRIO){(3)/直到空閑任務
OS_ENTER_CRITICAL(); if(ptcb->OSTCBDly!=0){ if(--ptcb->OSTCBDly==0){ if(!(ptcb->OSTCBStat&OS_STAT_SUSPEND)){(4)/被任務掛起的函數(shù)OSTaskSuspend()掛起的任務則不會進入就緒態(tài) OSRdyGrp|=ptcb->OSTCBBitY;(5)/當某任務的任務控制塊中的時間延時項OSTCBDly減到了零,這個任務就進入了就緒態(tài)
OSRdyTbl[ptcb->OSTCBY]|=ptcb->OSTCBBitX;} else{ptcb->OSTCBDly=1;}}} ptcb=ptcb->OSTCBNext;OS_EXIT_CRITICAL();} OS_ENTER_CRITICAL();(6) OSTime++;(7)/調用OSTime()累加從開機以來的時間
OS_EXIT_CRITICAL();}OSTimTick()的執(zhí)行時間與應用程序中建立了多少個任務成正比。用戶也可以從任務級調用OSTimeTick(),首先要建立一個高于應用程序中所有其它任務優(yōu)先級的任務,然后,時鐘節(jié)拍中斷服務子程序利用信號量或郵箱發(fā)信號給這個高優(yōu)先級的任務。時鐘節(jié)拍任務TickTask()
作為時鐘節(jié)拍中斷服務子程序
voidTickTask(void*pdata){pdata=pdata; for(;;){ OSMboxPend(...);/*等待從時鐘節(jié)拍中斷服務程序發(fā)來的信號*/ OSTimeTick(); }}用戶要先建立一個郵箱(初始化成NULL),用于發(fā)信號給上述任務告知時鐘節(jié)拍中斷已經發(fā)生了。時鐘節(jié)拍中斷服務函數(shù)
OSTickISR()做節(jié)拍服務程序
voidOSTickISR(void){保存處理器寄存器的值;調用OSIntEnter()或是將OSIntNesting加1;
發(fā)送一個‘空’消息(例如,(void*)1)到時鐘節(jié)拍的郵箱;
調用OSIntExit();恢復處理器寄存器的值;執(zhí)行中斷返回指令;}μC/OS-Ⅱ初始化
在調用μC/OS-Ⅱ的任何其它服務之前,μC/OS-Ⅱ要求用戶首先調用系統(tǒng)初始化函數(shù)OSIint()初始化μC/OS-Ⅱ所有的變量和數(shù)據(jù)結構(見OS_CORE.C)。OSInit()建立空閑任務idletask,這個任務總是處于就緒態(tài)的??臻e任務OSTaskIdle()的優(yōu)先級總是設成最低,即OS_LOWEST_PRIO。如果統(tǒng)計任務允許OS_TASK_STAT_EN和任務建立擴展允許都設為1,則OSInit()還得建立統(tǒng)計任務OSTaskStat()并且讓其進入就緒態(tài)。OSTaskStat的優(yōu)先級總是設為OS_LOWEST_PRIO-1。μC/OS-Ⅱ初始化
調用OSInit()之后,一些μC/OS-Ⅱ變量和數(shù)據(jù)結構之間的關系如下圖所示。假設:在文件OS_CFG.H中,OS_TASK_STAT_EN是設為1的。在文件OS_CFG.H中,OS_LOWEST_PRIO是設為63的。在文件OS_CFG.H中,最多任務數(shù)OS_MAX_TASKS是設成大于2的。以上兩個任務(空閑與統(tǒng)計)的任務控制塊(OS_TCBs)是用雙向鏈表鏈接在一起的,OSTCBList指向這個鏈表的起始處。當建立一個任務時,這個任務總是被放在這個鏈表的起始處。即OSTCBList總是指向最后建立的那個任務,鏈的終點指向空字符NULL(也就是零
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 個人土地合作經營合同范本
- 個人分期付款還款合同范本2025
- 專賣店租賃合同協(xié)議
- 個體戶與合作方合同范本
- 個人木材轉讓合同書其五
- 臨時建筑租賃及安裝合同
- 上海公寓租賃合同協(xié)議
- 人事檔案關系代理保管專用合同書版
- 產品售后保修合同協(xié)議
- 二手房買賣合同標準模板
- 2025年南京信息職業(yè)技術學院高職單招職業(yè)技能測試近5年??及鎱⒖碱}庫含答案解析
- 微生物組與膽汁性肝硬化
- 混床計算書(新)
- 1325木工雕刻機操作系統(tǒng)說明書
- 初中衡水體英語(28篇)
- 斯瓦希里語輕松入門(完整版)實用資料
- 復古國潮風中國風春暖花開PPT
- GB/T 2317.2-2000電力金具電暈和無線電干擾試驗
- 機動車輛保險理賠實務2023版
- 病原微生物實驗室標準操作規(guī)程sop文件
- 最完善的高速公路機電監(jiān)理細則
評論
0/150
提交評論