天天看點

嵌入式實時作業系統ucosii原理及應用(任哲)

本文是《嵌入式實時作業系統ucosii原理及應用(任哲)》一書第三章的閱讀筆記,知識點多為摘錄,若希望深入了解,請購買該書認真研讀。由于一些知識比較零散,記起來不大友善,又習慣畫圖輔助記憶,剛好想起一款比較好用的思維導圖,就順手拿來用一用了(絕非打廣告),導圖中包含部分備注。

嵌入式實時作業系統ucosii原理及應用(任哲)

腦圖連結及密碼:http://naotu.baidu.com/file/c550d674fa54bd29588c31c5bd682f4f?token=8e71f5732699f4b6 密碼: v6um

嵌入式實時作業系統ucosii原理及應用(任哲)

可以看出:A)任務必須先從睡眠狀态進入就緒狀态,才能在合适的時機被運作;B)隻能從運作狀态進入中斷服務狀态;C)隻能從運作狀态進入等待狀态。

前面一章我們已經講過:大多數任務(尤其是使用者任務)是一個無限循環結構,在這個循環中,系統響應中斷請求,進入中斷服務函數進行其他操作。但是,有時任務中的一些操作是不允許被中斷打斷的,為此,我們可以在任務函數程式代碼中添加關中斷函數和開中斷函數,則在這兩個函數之間的代碼,執行過程不會被打斷,該段代碼稱為臨界段。ucosii中用兩個宏:OS_ENTER_CRITICAL( )、OS_EXIT_CRATICAL( )分别實作關中斷和開中段。從程式設計角度看,一個ucosii任務的代碼就是一個C語言函數,為了可以傳遞各種不同類型的資料甚至是函數,ucosii把任務參數定義成了一個void類型的指針。

使用者應用程式的一般結構:

在ucosii中,main函數與任務函數的地位是平等的,雖然任務是在main函數中初始化的,但是任務和main的運作與中斷是由作業系統排程的,也就是說,作為程式運作的入口函數,main函數必須完成作業系統的初始化、任務的建立、作業系統的啟動,最後把系統的排程權交回給作業系統。

void MyTask1(void *pdata)

{

for( ; ; )

{

//這上面的代碼執行時可以被打斷

OS_ENTER_CRITICAL( );

//臨界段

//這中間執行的代碼不可以被打斷

OS_ENTER_CRITICAL( );

}

}

void MyTask2(void *pdata)

{

for( ; ; )

{

//這上面的代碼執行時可以被打斷

OS_ENTER_CRITICAL( );

//臨界段

//這中間執行的代碼不可以被打斷

OS_ENTER_CRITICAL( );

}

}

void main(void)

{

OS_Init( );

OSTaskCreate(MyTask1,...);

OSTaskCreate(MyTask2,...);

OS_Start( );

}

作業系統運作時,一定有某段時間處于空閑狀态,但是CPU是不可以停下來的,除非斷電。為此,ucosii定義了兩個系統任務:空閑任務和統計任務。空閑任務是使用者應用程式必須使用的,統計任務是使用者程式可選擇使用的。

//作業系統定義的空閑任務

void OS_TaskIdle(void *pdata)

{

#if(OS_CRITICAL_METHOD == 3)

OS_CPU_SR cpu_sr;

#endif

//部分C編譯器會對定義了卻沒有使用的變量報錯

pdata = pdata;

for( ; ; )

{

OS_ENTER_CRITICAL( );

OSIdleCtr++; //記錄空閑任務運作次數

OS_EXIT_CRITICAL( );

//一般還會加上下面這個函數,使用者可以在該函數中寫使用者希望執行的代碼

//一般函數内寫的是讓CPU進入低功耗模式的指令

//該函數總是處于就緒狀态的

OSTaskIdleHook( );

}

}

至于統計任務,該任務每秒計算一次CPU在機關時間内被使用的時間,并把計算結果以百分比的形式存放在變量OSCPUsage中,進而使得應用程式可以了解CPU的使用率。

當不同任務同時需要運作時,系統利用優先級判斷哪個先執行,由于大多數情況下任務數少于64個,使用者可以通過修改OS_CFG.h檔案的OS_LOWEST_PRIO來确定最低優先級(優先級為:0~OS_LOWEST_PRIO)。OS_LOWEST_PRIO賦給空閑任務,如果使用者使用了統計任務,系統還會把(OS_LOWEST_PRIO-1)賦給統計任務,使用者可以使用的優先級範圍為:0~OS_LOWEST_PRIO-2,在建立任務時,使用者必須指定任務的優先級(指定OSTaskCreate( )第四個參數)。

任務堆棧:任務的運作環境,在程式設計上展現為一數組,出棧入棧遵循LIFO後進先出的原則。任務堆棧的定義:宏定義設定堆棧存儲機關(可了解為資料類型)type、宏定義設定堆棧大小size、用type定義大小為size的數組用作任務堆棧。

任務的定義:使用系統函數OSTaskCreate(指向任務代碼的指針,傳遞給任務的參數,任務堆棧的棧頂指針,任務優先級),需要提醒的是,處理器不同,棧的生長方向不同,stm32f103的棧生長方向是從高位址到低位址,是以棧頂指針是堆棧數組的最後一個成員的位址。

int 16位;unsigned int 位數與作業系統相關。

任務堆棧的初始化:由于任務的運作前,CPU的各個寄存器需要預置一些原始資料,包括指向任務的指針、程式狀态字PSW等,因為它們因任務不同而有差異,是以存儲在任務堆棧中,建立任務時将這些值放入堆棧中稱為堆棧的初始化。堆棧的初始化由OSTaskCreat( )函數調用OSTaskStkInit( )實作,使用者除了在移植作業系統時修改它,基本不會接觸到這個函數。

附上一篇的腦圖連結及密碼:http://naotu.baidu.com/file/8910fc6778b390b730a755e610790477?token=86bdf5ad5bee75c3 密碼: SC2h