把一個大型任務分解成多個小任務,然後在計算機中通過運行這些小任務,最終達到完成大任務的目的。在μC/OS-II中,與上述那些小任務對應的程序實體就叫做“任務”(實質上是一個線程–有私有空間的任務叫做進程,沒有私有空間的任務叫做線程),μC/OS-II就是一個能對這些小任務的運行進行管理和調度的多任務操作系統。
從應用程序設計的角度來看,μC/OS-II的任務就是一個用戶編寫的C函數和與之相關聯的一些數據結構而構成的一個實體。在內存中應該存有任務的代碼和與該任務配套的堆棧。
一個完整的任務應該有如下三部分:
1. 任務代碼(程序)
2. 任務的私有堆棧(用以保護運行環境)
3. 任務控制塊(提供私有堆棧也是虛擬處理器的位置)
μC/OS-Ⅱ的任務管理函數共有9個:
- 2個建立任務函數
- 1個堆棧檢驗函數
- 1個優先級變更函數
- 1個任務掛起函數
- 1個任務恢復函數
- 1個刪除任務函數
- 1個請求刪除任務函數
- 1個任務信息的獲取函數
這些任務管理函數後面再詳細分析,這裏重點講一下任務堆棧。
任務棧是用於保存任務函數中所用寄存器、變量和數據結構的堆棧。µC/OS-Ⅱ的任務棧必須聲明爲OS_STK
類型,它有如下特點:(1) 每個任務都可以有自己不同的堆棧空間;(2) 堆棧聲明應放置在函數的外面;(3) 堆棧由連續的內存空間組成。
每個任務在創建的時候都要調用OSTaskStkInit()
初始化任務堆棧。初始化任務堆棧需要清楚處理器平臺堆棧的生長方向,Corex-M3的堆棧是向下生長的。
如下定義的任務堆棧,則棧頂指針應STARTUP_TASK_STK_SIZE-1]
static OS_STK startup_task_stk[STARTUP_TASK_STK_SIZE]; //define stack
堆棧初始化在不同的處理器平臺有差異,以下爲在STM32上移植系統的堆棧初始化函數源碼,其實任務堆棧的初始化就是對該任務的虛擬處理器的初始化(復位)。
OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt)
{
OS_STK *stk;
(void)opt; /* 'opt' is not used, prevent warning */
stk = ptos; /* Load stack pointer */
/* Registers stacked as if auto-saved on exception */
*(stk) = (INT32U)0x01000000L; /* xPSR */
*(--stk) = (INT32U)task; /* Entry Point */
*(--stk) = (INT32U)0xFFFFFFFEL; /* R14 (LR) (init value will cause fault if ever used)*/
*(--stk) = (INT32U)0x12121212L; /* R12 */
*(--stk) = (INT32U)0x03030303L; /* R3 */
*(--stk) = (INT32U)0x02020202L; /* R2 */
*(--stk) = (INT32U)0x01010101L; /* R1 */
*(--stk) = (INT32U)p_arg; /* R0 : argument */
/* Remaining registers saved on process stack */
*(--stk) = (INT32U)0x11111111L; /* R11 */
*(--stk) = (INT32U)0x10101010L; /* R10 */
*(--stk) = (INT32U)0x09090909L; /* R9 */
*(--stk) = (INT32U)0x08080808L; /* R8 */
*(--stk) = (INT32U)0x07070707L; /* R7 */
*(--stk) = (INT32U)0x06060606L; /* R6 */
*(--stk) = (INT32U)0x05050505L; /* R5 */
*(--stk) = (INT32U)0x04040404L; /* R4 */
return (stk);
}
OSTaskStkInit()
在Cortex-M3中主要功能爲初始化任務的棧的桔構,使任務的棧看起來就好像剛發生了一箇中斷一樣。Cortex-M3中斷時,xPSR、PC、LR、R12、R3--R0
自動入棧,R11--R4
需手動保存。這裏的值R1--R12
沒有實際意義,相應的數值只爲調試方便。
初始化後各寄存器的值如下
xPSR=0x0100000
,xPSR
T
位置1,否則第一次執行任務是Fault。
PC=task
,指向任務入口。
R14=0xFFFFFFFE
,是一個非法值,主要目的是不讓使用R14
,任務不能返回。
R0=p_arg
,用於傳遞任務的參數。