版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
μC/OS-II中 的
6/24/20241任務的狀態(tài)及其轉(zhuǎn)換正在運行的任務,需要等待一段時間或需要等待一個事件發(fā)生再運行時,該任務就會把CPU的使用權讓給別的任務而使任務進入等待狀態(tài),利用等待函數(shù)OSTimeDly()等實現(xiàn)。任務在沒有被配備任務控制塊或被剝奪了任務控制塊時的狀態(tài)叫做任務的睡眠狀態(tài)
系統(tǒng)為任務配備了任務控制塊且在任務就緒表中進行了就緒登記,這時任務的狀態(tài)叫做就緒狀態(tài)。
處于就緒狀態(tài)的任務如果經(jīng)調(diào)度器判斷獲得了CPU的使用權,則任務就進入運行狀態(tài)
一個正在運行的任務一旦響應中斷申請就會中止運行而去執(zhí)行中斷服務程序,這時任務的狀態(tài)叫做中斷服務狀態(tài)
6/24/20242前面談到,一個任務的任務控制塊的主要作用就是保存該任務的虛擬處理器的堆棧指針寄存器SP。其實,隨著任務管理工作的復雜性的提高,它還應該保存一些其他信息。任務控制塊——任務在系統(tǒng)中的身份證
由于系統(tǒng)存在著多個任務,于是系統(tǒng)如何來識別并管理一個任務就是一個需要解決的問題。識別一個任務的最直接的辦法是為每一個任務起一個名稱。由于μC/OS-II中的任務都有一個惟一的優(yōu)先級別,因此μC/OS-II是用任務的優(yōu)先級來作為任務的標識的。所以,任務控制塊還要來保存該任務的優(yōu)先級別。另外,前面也談到,一個任務在不同的時刻還處于不同的狀態(tài),顯然,記錄了任務狀態(tài)的數(shù)據(jù)也應該保存到任務控制塊中?;谏鲜鲈?,系統(tǒng)必須為每個任務創(chuàng)建一個保存與該任務有關的相關信息的數(shù)據(jù)結(jié)構,這個數(shù)據(jù)結(jié)構就叫做該任務的任務控制塊(TCB)。任務控制塊結(jié)構的主要成員typedefstructos_tcb{
OS_STK*OSTCBStkPtr; //指向任務堆棧棧頂?shù)闹羔?/p>
……
INT8U OSTCBStat; //任務的當前狀態(tài)標志
INT8U OSTCBPrio; //任務的優(yōu)先級別
……}OS_TCB;
任務控制塊是不是像我們?nèi)嗽谝粋€國家中的身份證?(其實,系統(tǒng)中的所有資源都應該有身份證。)6/24/20243任務在內(nèi)存中的結(jié)構6/24/20244用戶任務代碼的一般結(jié)構
voidMyTask(void*pdata){for(;;){可以被中斷的用戶代碼;OS_ENTER_CRITICAL();//進入臨界段(關中斷)
不可以被中斷的用戶代碼;OS_EXIT_CRITICAL(); //退出臨界段(開中斷)可以被中斷的用戶代碼;}}臨界段無限循環(huán)于是可以這樣說,μC/OS-II任務的代碼結(jié)構是一個可以帶有臨界段的無限循環(huán)。
6/24/20245系統(tǒng)提供的空閑任務
在多任務系統(tǒng)運行時,系統(tǒng)經(jīng)常會在某個時間內(nèi)無用戶任務可運行而處于所謂的空閑狀態(tài),為了使CPU在沒有用戶任務可執(zhí)行的時候有事可做,μC/OS-II提供了一個叫做空閑任務OSTaskIdle()的系統(tǒng)任務
voidOSTaskIdle(void*pdata){#ifOS_CRITICAL_METHOD==3 OS_CPU_SRcpu_sr;#endif
pdata=pdata; //防止某些編譯器報錯
for(;;) { OS_ENTER_CRITICAL();//關閉中斷 OSdleCtr++; //計數(shù) OS_EXIT_CRITICAL();
//開放中斷 }}空閑任務只是做了一個計數(shù)工作注意!空閑任務中沒有調(diào)用任務延時函數(shù)μC/OS-II規(guī)定,一個用戶應用程序必須使用這個空閑任務,而且這個任務是不能用軟件來刪除的
6/24/20246系統(tǒng)提供的另一個任務——統(tǒng)計任務μC/OS-II提供的另一個系統(tǒng)任務是統(tǒng)計任務OSTaskStat()。這個統(tǒng)計任務每秒計算一次CPU在單位時間內(nèi)被使用的時間,并把計算結(jié)果以百分比的形式存放在變量OSCPUsage中,以便應用程序通過訪問它來了解CPU的利用率,所以這個系統(tǒng)任務OSTaskStat()叫做統(tǒng)計任務
6/24/20247
任務的優(yōu)先權及優(yōu)先級別
μC/OS_II把任務的優(yōu)先權分為64個優(yōu)先級別,每一個級別都用一個數(shù)字來表示。數(shù)字0表示任務的優(yōu)先級別最高,數(shù)字越大則表示任務的優(yōu)先級別越低
用戶可以根據(jù)應用程序的需要,在文件OS_CFG.H中通過給表示最低優(yōu)先級別的常數(shù)OS_LOWEST_PRIO賦值的方法,來說明應用程序中任務優(yōu)先級別的數(shù)目。該常數(shù)一旦被定義,則意味著系統(tǒng)中可供使用的優(yōu)先級別為:0,1,2,……,OS_LOWEST_PRIO,共OS_LOWEST_PRIO+1個
固定地,系統(tǒng)總是把最低優(yōu)先級別OS_LOWEST_PRIO自動賦給空閑任務。如果應用程序中還使用了統(tǒng)計任務,系統(tǒng)則會把優(yōu)先級別OS_LOWEST_PRIO-1自動賦給統(tǒng)計任務,因此用戶任務可以使用的優(yōu)先級別是:0,1,2…OS_LOWEST_PRIO-2,共OS_LOWEST_PRIO-1個
6/24/20248
任務堆棧
保存CPU寄存器中的內(nèi)容及存儲任務私有數(shù)據(jù)的需要,每個任務都應該配有自己的堆棧,任務堆棧是任務的重要的組成部分在應用程序中定義任務堆棧的棧區(qū)非常簡單,即定義一個OS_STK類型的一個數(shù)組并在創(chuàng)建一個任務時把這個數(shù)組的地址賦給該任務就可以了。例如:
//定義堆棧的長度#define TASK_STK_SIZE 512//定義一個數(shù)組來作為任務堆棧OS_STKTaskStk[TASK_STK_SIZE]; typedefunsignedintOS_STK;//這是系統(tǒng)定義的一個數(shù)據(jù)類型voidmain(void){ …… OSTaskCreate( MyTask, //任務的指針 &MyTaskAgu, //傳遞給任務的參數(shù) &MyTaskStk[MyTaskStkN-1],//任務堆棧棧頂?shù)刂? 20 //任務的優(yōu)先級別 ); ……}在創(chuàng)建用戶任務時,要傳遞任務的堆棧指針和任務優(yōu)先級別使用函數(shù)OSTaskCreate()創(chuàng)建任務時,一定要注意所使用的處理器對堆棧增長方向的支持是向上的還是向下的
6/24/20249任務堆棧的初始化
應用程序在創(chuàng)建一個新任務的時候,必須把在系統(tǒng)啟動這個任務時CPU各寄存器所需要的初始數(shù)據(jù)(任務指針、任務堆棧指針、程序狀態(tài)字等等),事先存放在任務的堆棧中
μC/OS-II在創(chuàng)建任務函數(shù)OSTaskCreate()中通過調(diào)用任務堆棧初始化函數(shù)OSTaskStkInit()來完成任務堆棧初始化工作的
它的原型如下:
OS_STK*OSTaskStkInit( void(*task)(void*pd), void*pdato, OS_STK*ptos, INT16Uopt );由于各種處理器的寄存器及對堆棧的操作方式不盡相同,因此該函數(shù)需要用戶在進行μC/OS-II的移植時,按所使用的處理器由用戶來編寫。實現(xiàn)這個函數(shù)的具體細節(jié),將在本書有關μC/OS-II移植的章節(jié)中做進一步的介紹
其實,任務堆棧的初始化就是對該任務的虛擬處理器的初始化(復位)。
6/24/202410任務控制塊 (OS_TCB) 及任務控制塊鏈表
μC/OS-II用來記錄任務的堆棧指針、任務的當前狀態(tài)、任務的優(yōu)先級別等一些與任務管理有關的屬性的表就叫做任務控制塊
任務控制塊就相當于是一個任務的身份證,沒有任務控制塊的任務是不能被系統(tǒng)承認和管理的
任務控制塊結(jié)構的主要成員typedefstructos_tcb{
OS_STK*OSTCBStkPtr;//指向任務堆棧棧頂?shù)闹羔?/p>
……
structos_tcb*OSTCBNext;//指向后一個任務控制塊的指針
structos_tcb*OSTCBPrev;
//指向前一個任務控制塊的指針
……
INT16U OSTCBDly; //任務等待的時限(節(jié)拍數(shù))
INT8U OSTCBStat; //任務的當前狀態(tài)標志
INT8U OSTCBPrio; //任務的優(yōu)先級別
……}OS_TCB;任務控制塊鏈表空任務控制塊鏈表當應用程序調(diào)用函數(shù)OSTaskCreate()創(chuàng)建一個任務時,這個函數(shù)會調(diào)用系統(tǒng)函數(shù)OSTCBInit()來為任務控制塊進行初始化。這個函數(shù)首先為被創(chuàng)建任務從空任務控制塊鏈表獲取一個任務控制塊,然后用任務的屬性對任務控制塊各個成員進行賦值,最后再把這個任務控制塊鏈入到任務控制塊鏈表的頭部
當進行系統(tǒng)初始化時,初始化函數(shù)OSInit();會按用戶提供的任務數(shù)為系統(tǒng)創(chuàng)建具有相應數(shù)量的任務控制塊并把它們鏈接為一個鏈表。 由于這些任務控制塊還沒有對應的任務,故這個鏈表叫做空任務塊鏈表。即相當于是一些空白的身份證。
6/24/202411 任務就緒表 及 任務調(diào)度
多任務操作系統(tǒng)的核心工作就是任務調(diào)度。所謂調(diào)度,就是通過一個算法在多個任務中確定該運行的任務,做這項工作的函數(shù)就叫做調(diào)度器。
μC/OS_II進行任務調(diào)度的思想是“近似地每時每刻總是讓優(yōu)先級最高的就緒任務處于運行狀態(tài)”。為了保證這一點,它在系統(tǒng)或用戶任務調(diào)用系統(tǒng)函數(shù)及執(zhí)行中斷服務程序結(jié)束時總是調(diào)用調(diào)度器,來確定應該運行的任務并運行它。μC/OS_II進行任務調(diào)度的依據(jù)就是任務就緒表
為了能夠使系統(tǒng)清楚地知道,系統(tǒng)中哪些任務已經(jīng)就緒,哪些還沒有就緒,μC/OS_II在RAM中設立了一個記錄表,系統(tǒng)中的每個任務都在這個表中占據(jù)一個位置,并用這個位置的狀態(tài)(1或者0)來表示任務是否處于就緒狀態(tài),這個表就叫做任務就緒狀態(tài)表,簡稱叫任務就緒表
任務就緒表就是一個二維數(shù)組OSRdyTbl[]6/24/202412為加快訪問任務就緒表的速度,系統(tǒng)定義了一個變量OSRdyGrp來表明就緒表每行中是否存在就緒任務。6/24/202413OSRdyTbl[]1/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/01/0OSRdyGrp
D7D6D5D4D3D2D1D0
1/01/01/01/01/01/01/01/0任務就緒表的示意圖01234567xy012345676/24/202414OSRdyGrp
D7D6D5D4D3D2D1D0
11110000prio=29D7D6D5D4D3D2D1D0
1D7D6D5D4D3D2D1D0
1OSRdyTbl[3]把prio為29的任務置為就緒狀態(tài)YXOSRdyGrp|=OSMapTbl[prio>>3];OSRdyTbl[prio>>3]|=OSMapTbl[prio&0x07];在程序中,可以用類似下面的代碼把優(yōu)先級別為prio的任務置為就緒狀態(tài):
OSRdyGrp|=OSMapTbl[prio>>3];OSRdyTbl[prio>>3]|=OSMapTbl[prio&0x07];如果要使一個優(yōu)先級別為prio的任務脫離就緒狀態(tài)則可使用如下類似代碼:
if((OSRdyTbl[prio>>3]&=~OSMapTbl[prio&0x07])==0) OSRdyGrp&=~OSMapTbl[prio>>3];
356/24/202415OSRdyGrp
D7D6D5D4D3D2D1D0
11110000prio=29D7D6D5D4D3D2D1D0
1D7D6D5D4D3D2D1D0
1OSRdyTbl[y]x=OSUnMapTal[OSRdyTbl[y]];11000000000000y=OSUnMapTal[OSRdyGrp];圖5-6在就緒表中查找最高優(yōu)先級別任務的過程從任務就緒表中獲取優(yōu)先級別最高的就緒任務可用如下類似的代碼:
y=OSUnMapTal[OSRdyGrp];
//D5、D4、D3位x=OSUnMapTal[OSRdyTbl[y]];//D2、D1、D0位prio=(y<<3)+x;
//優(yōu)先級別
或
y=OSUnMapTbl[OSRdyGrp];prio=(INT8U)((y<<3)+OSUnMapTbl[OSRdyTbl[y]]);6/24/202416優(yōu)先級判定表OSUnMapTbl[256](os_core.c)INT8UconstOSUnMapTbl[]={0,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0};舉例:如OSRdyGrp的值為00101000B,即0X28,則查得OSUnMapTbl[OSRdyGrp]的值是3,它相應于OSRdyGrp中的第3位置1;如OSRdyTbl[3]的值是11100100B,即0XE4,則查OSUnMapTbl[OSRdyTbl[3]]的值是2,則進入就緒態(tài)的最高任務優(yōu)先級Prio=3*8+2=26
6/24/202417小結(jié)系統(tǒng)通過查找任務就緒表來獲取待運行任務的優(yōu)先級優(yōu)先級6/24/202418任務切換過程獲得待運行任務的任務控制塊恢復待運行任務的運行環(huán)境處理器的PC=任務堆棧中的斷點地址處理器的SP=任務塊中保存的SP如何獲得待運行任務的任務控制塊?根據(jù)就緒表獲得待運行任務的任務控制塊指針其實,調(diào)度器在進行調(diào)度時,在這個位置還要進行一下判斷:究竟是待運行任務是否為當前任務,如果是,則不切換;如果不是才切換,而且還要保存被中止任務的運行環(huán)境。6/24/2024191.
任務切換宏
OS_TASK_SW()
任務切換就是中止正在運行的任務(當前任務),轉(zhuǎn)而去運行另外一個任務的操作,當然這個任務應該是就緒任務中優(yōu)先級別最高的那個任務
先保護被中止任務的斷點數(shù)據(jù)后恢復待運行任務的斷點數(shù)據(jù)不要企圖用PUSH和POP指令來使程序計數(shù)器PC壓棧和出棧,因為沒有這樣的指令。只好變通一下了。中斷動作和過程調(diào)用指令可以使PC壓棧;中斷返回指令可以使PC出棧。因此任務切換OSCtxSw()必定是一個中斷服務程序。需要由宏OS_TASK_SW()來引發(fā)一次中斷或者一次調(diào)用來使 OSCtxSw() 執(zhí)行任務切換工作6/24/202420調(diào)度時機很容易想到的調(diào)度時機就是定時調(diào)度。對于實時系統(tǒng)來說,應該盡可能地實現(xiàn)即時調(diào)度。6/24/202421用函數(shù)OSTaskCreate()創(chuàng)建任務
應用程序通過調(diào)用OSTaskCreate()函數(shù)來創(chuàng)建一個任務,OSTaskCreate()函數(shù)的原型如下:
INT8UOSTaskCreate(void(*task)(void*pd),//指向任務的指針void*pdata, //傳遞給任務的參數(shù)OS_STK*ptos, //指向任務堆棧棧頂?shù)闹羔業(yè)NT8Uprio //任務的優(yōu)先級)6/24/202422
創(chuàng)建任務的一般方法
一般來說,任務可以在調(diào)用函數(shù)OSStart()啟動任務調(diào)度之前來創(chuàng)建,也可以在任務中來創(chuàng)建。但是,μC/OS-II有一個規(guī)定:在調(diào)用啟動任務函數(shù)OSStart()之前,必須已經(jīng)創(chuàng)建了至少一個任務。因此,人們習慣上在調(diào)用函數(shù)OSStart()之前先創(chuàng)建一個任務,并賦予它最高的優(yōu)先級別,從而使它成為起始任務。然后在這個起始任務中,再創(chuàng)建其他各任務。如果要使用系統(tǒng)提供的統(tǒng)計任務,則統(tǒng)計任務的初始化函數(shù)也必須在這個起始任務中來調(diào)用
voidmain(void){ …… OSInit(); //對μC/OS-II進行初始化 ……
OSTaskCreate(TaskStart,……);//創(chuàng)建任務TaskStart
OSStart(); //開始多任務調(diào)度}
voidTaskStart(void*pdata){ ……//在這個位置安裝并啟動μC/OS-II的時鐘 OSStatInit(); //初始化統(tǒng)計任務 ……//在這個位置創(chuàng)建其他任務 for(;;) { 起始任務TaskStart的代碼 }}6/24/202423μC/OS-II的初始化
在使用μC/OS-II的所有服務之前,必須要調(diào)用μC/OS-II的初始化函數(shù)OSInit()對μC/OS-II自身的運行環(huán)境進行初始化。
函數(shù)OSInit()將對μC/OS-II的所有的全局變量和數(shù)據(jù)結(jié)構進行初始化,同時創(chuàng)建空閑任務OSTaskIdle,并賦之以最低的優(yōu)先級別和永遠的就緒狀態(tài)。如果用戶應用程序還要使用統(tǒng)計任務的話(常數(shù)OS_TASK_STAT_EN=1),則OSInit()還要以優(yōu)先級別為OS_LOWEST_PRIO-1來創(chuàng)建統(tǒng)計任務
初始化函數(shù)OSInit()對數(shù)據(jù)結(jié)構進行初始化時,主要要創(chuàng)建包括空任務控制塊鏈表在內(nèi)的5個空數(shù)據(jù)緩沖區(qū)。同時,為了可以快速地查詢?nèi)蝿湛刂茐K鏈表中的各個元素,初始化函數(shù)OSInit()還要創(chuàng)建一個數(shù)組OSTCBPrioTbl[OS_LOWEST_PRIO+1],在這個數(shù)組中,按任務的優(yōu)先級別的順序把任務控制塊的指針存放在了對應的元素中
6/24/202424μC/OS-II的啟動μC/OS-II進行任務的管理是從調(diào)用啟動函數(shù)OSStart()開始的,當然其前提條件是在調(diào)用該函數(shù)之前至少創(chuàng)建了一個用戶任務
6/24/202425
第3章
μC/OS-Ⅱ的中斷和時鐘
6/24/202426本章主要內(nèi)容:6/24/202427μC/OS-II系統(tǒng)響應中斷的過程μC/OS-II系統(tǒng)響應中斷的過程為:系統(tǒng)接收到中斷請求后,這時如果CPU處于中斷允許狀態(tài)(即中斷是開放的),系統(tǒng)就會中止正在運行的當前任務,而按照中斷向量的指向轉(zhuǎn)而去運行中斷服務子程序;當中斷服務子程序的運行結(jié)束后,系統(tǒng)將會根據(jù)情況返回到被中止的任務繼續(xù)運行或者轉(zhuǎn)向運行另一個具有更高優(yōu)先級別的就緒任務。注意!中斷服務子程序運行結(jié)束之后,系統(tǒng)將會根據(jù)情況進行一次任務調(diào)度去運行優(yōu)先級別最高的就緒任務,而并不是一定要接續(xù)運行被中斷的任務的。6/24/202428中斷請求關閉中斷轉(zhuǎn)到中斷向量保存CPU寄存器通知內(nèi)核退出ISRISR給任務發(fā)信號中斷返回恢復CPU寄存器中斷響應中斷恢復中斷恢復任務響應時間任務響應時間中斷的響應過程無新高級任務則返回原任務通知內(nèi)核退出ISR恢復CPU寄存器中斷返回有新高級任務則運行高級任務通知內(nèi)核進入ISR6/24/202429voidOSIntEnter(void){if(OSRunning==TRUE){if(OSIntNesting<255){
OSIntNesting++;//中斷嵌套層數(shù)計數(shù)器加一}}}voidOSIntExit(void){#ifOS_CRITICAL_METHOD==3OS_CPU_SRcpu_sr;#endifif(OSRunning==TRUE){OS_ENTER_CRITICAL();if(OSIntNesting>0){OSIntNesting--; //中斷嵌套層數(shù)計數(shù)器減一}if((OSIntNesting==0)&&(OSLockNesting==0)){OSIntExitY=OSUnMapTbl[OSRdyGrp];OSPrioHighRdy=(INT8U)((OSIntExitY<<3)+OSUnMapTbl[OSRdyTbl[OSIntExitY]]);if(OSPrioHighRdy!=OSPrioCur){OSTCBHighRdy=OSTCBPrioTbl[OSPrioHighRdy];OSCtxSwCtr++;OSIntCtxSw();}}OS_EXIT_CRITICAL();}}6/24/202430在中斷服務程序中調(diào)用的負責任務切換工作的函數(shù)OSIntCtxSw()叫做中斷級任務切換函數(shù)
OSIntCtxSw(){OSTCBCur=OSTCBHighRdy;//任務控制塊的切換
OSPrioCur=OSPrioHighRdy;SP=OSTCBHighRdy->OSTCBStkPtr;//SP指向待運行任務堆棧用出棧指令把R1,R2,……彈入CPU的通用寄存器;RETI;//中斷返回,使PC指向待運行任務}6/24/202431應用程序中的臨界段
在應用程序中經(jīng)常有一些代碼段必須不受任何干擾地連續(xù)運行,這樣的代碼段叫做臨界段。因此,為了使臨界段在運行時不受中斷所打斷,在臨界段代碼前必須用關中斷指令使CPU屏蔽中斷請求,而在臨界段代碼后必須用開中斷指令解除屏蔽使得CPU可以響應中斷請求
由于各廠商生產(chǎn)的CPU和C編譯器的關中斷和開中斷的方法和指令不盡相同,為增強μC/OS-II的可移植性(即在μC/OS-II的各個C函數(shù)中盡可能地不出現(xiàn)匯編語言代碼),μC/OS-II用兩個宏來實現(xiàn)中斷的開放和關閉,而把與系統(tǒng)的硬件相關的關中斷和開中斷的指令分別封裝在這兩個宏中:
OS_ENTER_CRITICAL() OS_EXIT_CRITICAL()
第一種方法最簡單,即直接使用處理器的開中斷和關中斷指令來實現(xiàn)宏,這時需要令常數(shù)OS_CRITICAL_METHOD=1。其示意性代碼為:
#defineOS_ENTER_CRITICAL()\ asm(“DI”) \\關中斷
#defineOS_EXIT_CRITICAL()\ asm(“EI”)
\\開中斷
第二種方法稍微復雜一些,但可以使CPU中斷允許標志的狀態(tài),在臨界段前和臨界段后不發(fā)生改變。在宏OS_ENTER_CRITICAL()中,把CPU的允許中斷標志保持到堆棧中,然后再關閉中斷,這樣在臨界段結(jié)束時,即在調(diào)用宏OS_EXIT_CRITICAL()時只要把堆棧中保存的CPU允許中斷狀態(tài)恢復就可以了。這兩個宏的示意性代碼如下:
#defineOS_ENTER_CRITICAL()asm(“PUSH PSW”)/*通過保存程序狀態(tài)字來保存中
斷允許標志*/asm(“DI”)
//關中斷#defineOS_EXIT_CRITICAL()asm(“POP PSW”)//恢復中斷允許標志asm(“EI”)//開中斷
6/24/202432μC/OS-II的系統(tǒng)時鐘μC/OS-II與大多數(shù)計算機系統(tǒng)一樣,用硬件定時器產(chǎn)生一個周期為ms級的周期性中斷來實現(xiàn)系統(tǒng)時鐘,最小的時鐘單位就是兩次中斷之間相間隔的時間,這個最小時鐘單位叫做時鐘節(jié)拍(TimeTick)。硬件定時器以時鐘節(jié)拍為周期定時地產(chǎn)生中斷,該中斷的中斷服務程序叫做OSTickISR()。中斷服務程序通過調(diào)用函數(shù)OSTimeTick()來完成系統(tǒng)在每個時鐘節(jié)拍時需要做的工作。voidOSTickISR(void){ 保存CPU寄存器; 調(diào)用OSIntEnter(); //記錄中斷嵌套層數(shù) if(OSIntNesting==1; { OSTCBCur->OSTCBStkPtr=SP;//保存堆棧指針 }
調(diào)用OSTimeTick(); //節(jié)拍處理 清除中斷; 開中斷; 調(diào)用OSIntExit(); //中斷嵌套層數(shù)減一
恢復CPU寄存器; 中斷返回;}
這是系統(tǒng)時鐘中斷服務程序voidOSTimeTick(void){ ……OSTimeTickHook(); ……
OSTime++; //記錄節(jié)拍數(shù)……if(OSRunning==TRUE){
ptcb=OSTCBList;while(ptcb->OSTCBPrio!=OS_IDLE_PRIO)
{OS_ENTER_CRITICAL();
if(ptcb->OSTCBDly!=0) {if(--ptcb->OSTCBDly==0)//任務的延時時間減一 {if((ptcb->OSTCBStat&OS_STAT_SUSPEND)
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 軟件工程師勞動合同樣本
- 2024醫(yī)院托管合作經(jīng)營合同
- 2024家電產(chǎn)品配送合同書模板
- 2024標準委托代理合同格式
- 2024下載裝飾工程承包合同書
- 2024年紙張產(chǎn)品購買合同
- 員工試用期間工作表現(xiàn)評估
- 2024年勞務派遣服務合作協(xié)議
- 600字代辦委托協(xié)議范本
- 創(chuàng)業(yè)孵化基地租賃協(xié)議案例
- 工程詢價合同模板
- 事業(yè)單位招聘《綜合基礎知識》考試試題及答案
- 無錫風機吊裝施工方案
- 《突發(fā)事件應急預案管理辦法》知識培訓
- 江蘇省南京市建鄴區(qū)2024-2025學年九年級上學期期中考試物理試題(無答案)
- 中小學師德師風建設各項制度匯編
- 2024年保安員證考試題庫及答案(共260題)
- 公務員2024年國考申論真題(地市級)及參考答案
- XXXX酒店管理公司成立方案
- 民用無人機操控員執(zhí)照(CAAC)考試復習重點題及答案
- 疼痛科整體規(guī)劃和發(fā)展方案
評論
0/150
提交評論