任務控制塊tcb
在UCOS-II.H中定義了tcb結構:view plaincopy to clipboardprint?
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
typedef struct os_tcb {
/*指向任務堆棧棧頂的指針*/
OS_STK *OSTCBStkPtr;
#if OS_TASK_CREATE_EXT_EN > 0
/*指向任務控制塊擴展的指針*/
void *OSTCBExtPtr;
/*指向任務堆棧棧底的指針*/
OS_STK *OSTCBStkBottom;
/*任務堆棧的長度*/
INT32U OSTCBStkSize;
/*創(chuàng)建任務時的選擇項*/
INT16U OSTCBOpt;
/*目前未被使用*/
INT16U OSTCBId;
#endif
/*指向后一個任務控制塊的指針*/
struct os_tcb *OSTCBNext;
/*指向前一個任務控制塊的指針*/
struct os_tcb *OSTCBPrev;
#if OS_EVENT_EN
/*指向事件控制塊的指針*/
OS_EVENT *OSTCBEventPtr;
#endif
#if ((OS_Q_EN > 0) && (OS_MAX_QS > 0)) || (OS_MBOX_EN > 0)
/*指向傳遞給任務消息的指針*/
void *OSTCBMsg;
/* Message received from OSMboxPost() or OSQPost() */
#endif
#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)
#if OS_TASK_DEL_EN > 0
OS_FLAG_NODE *OSTCBFlagNode;
/* Pointer to event flag node */
#endif
OS_FLAGS OSTCBFlagsRdy;
/* Event flags that made task ready to run */
#endif
/*任務等待的時限*/
INT16U OSTCBDly;
/*任務的當前狀態(tài)標志*/
INT8U OSTCBStat;
BOOLEAN OSTCBPendTO;
/* Flag indicating PEND timed out (TRUE == timed out) */
/*任務的優(yōu)先級別*/
INT8U OSTCBPrio;
/* Task priority (0 == highest, 63 == lowest) */
/*用于快速訪問就緒表的數據*/
INT8U OSTCBX;
/* Bit position in group corresponding to task priority (0..7) */
INT8U OSTCBY;
/* Index into ready table corresponding to task priority */
INT8U OSTCBBitX;
/* Bit mask to access bit position in ready table */
INT8U OSTCBBitY;
/* Bit mask to access bit position in ready group */
#if OS_TASK_DEL_EN > 0
/*請求刪除任務時用到的標志*/
INT8U OSTCBDelReq;
/* Indicates whether a task needs to delete itself */
#endif
#if OS_TASK_PROFILE_EN > 0
INT32U OSTCBCtxSwCtr;
/* Number of time the task was switched in */
INT32U OSTCBCyclesTot;
/* Total number of clock cycles the task has been running */
INT32U OSTCBCyclesStart;
/* Snapshot of cycle counter at start of task resumption */
OS_STK *OSTCBStkBase;
/* Pointer to the beginning of the task stack */
INT32U OSTCBStkUsed;
/* Number of bytes used from the stack */
#endif
#if OS_TASK_NAME_SIZE > 1
char OSTCBTaskName[OS_TASK_NAME_SIZE];
#endif
} OS_TCB;
typedef struct os_tcb {
/*指向任務堆棧棧頂的指針*/
OS_STK *OSTCBStkPtr;
#if OS_TASK_CREATE_EXT_EN > 0
/*指向任務控制塊擴展的指針*/
void *OSTCBExtPtr;
/*指向任務堆棧棧底的指針*/
OS_STK *OSTCBStkBottom;
/*任務堆棧的長度*/
INT32U OSTCBStkSize;
/*創(chuàng)建任務時的選擇項*/
INT16U OSTCBOpt;
/*目前未被使用*/
INT16U OSTCBId;
#endif
/*指向后一個任務控制塊的指針*/
struct os_tcb *OSTCBNext;
/*指向前一個任務控制塊的指針*/
struct os_tcb *OSTCBPrev;
#if OS_EVENT_EN
/*指向事件控制塊的指針*/
OS_EVENT *OSTCBEventPtr;
#endif
#if ((OS_Q_EN > 0) && (OS_MAX_QS > 0)) || (OS_MBOX_EN > 0)
/*指向傳遞給任務消息的指針*/
void *OSTCBMsg;
/* Message received from OSMboxPost() or OSQPost() */
#endif
#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)
#if OS_TASK_DEL_EN > 0
OS_FLAG_NODE *OSTCBFlagNode;
/* Pointer to event flag node */
#endif
OS_FLAGS OSTCBFlagsRdy;
/* Event flags that made task ready to run */
#endif
/*任務等待的時限*/
INT16U OSTCBDly;
/*任務的當前狀態(tài)標志*/
INT8U OSTCBStat;
BOOLEAN OSTCBPendTO;
/* Flag indicating PEND timed out (TRUE == timed out) */
/*任務的優(yōu)先級別*/
INT8U OSTCBPrio;
/* Task priority (0 == highest, 63 == lowest) */
/*用于快速訪問就緒表的數據*/
INT8U OSTCBX;
/* Bit position in group corresponding to task priority (0..7) */
INT8U OSTCBY;
/* Index into ready table corresponding to task priority */
INT8U OSTCBBitX;
/* Bit mask to access bit position in ready table */
INT8U OSTCBBitY;
/* Bit mask to access bit position in ready group */
#if OS_TASK_DEL_EN > 0
/*請求刪除任務時用到的標志*/
INT8U OSTCBDelReq;
/* Indicates whether a task needs to delete itself */
#endif
#if OS_TASK_PROFILE_EN > 0
INT32U OSTCBCtxSwCtr;
/* Number of time the task was switched in */
INT32U OSTCBCyclesTot;
/* Total number of clock cycles the task has been running */
INT32U OSTCBCyclesStart;
/* Snapshot of cycle counter at start of task resumption */
OS_STK *OSTCBStkBase;
/* Pointer to the beginning of the task stack */
INT32U OSTCBStkUsed;
/* Number of bytes used from the stack */
#endif
#if OS_TASK_NAME_SIZE > 1
char OSTCBTaskName[OS_TASK_NAME_SIZE];
#endif
} OS_TCB;
UCOS用兩條鏈表來管理任務控制塊
1. 空任務塊鏈表:
是UCOS的全局數據結構,是用來管理TCB的申請和釋放,在OSInit()建立并初始化
view plaincopy to clipboardprint?
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
OSInit()
{
………
OS_InitTCBList(); //TCB鏈表初始化
………
}
OSInit()
{
………
OS_InitTCBList(); //TCB鏈表初始化
………
}
OS_InitTCBList():
TCB創(chuàng)建步驟:建立全局變量OSTCBTb1[]
view plaincopy to clipboardprint?
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
#define OS_EXT extern
OS_EXT OS_TCB OSTCBTbl[OS_MAX_TASKS + OS_N_SYS_TASKS];
OS_EXT OS_TCB *OSTCBFreeList;
#define OS_EXT extern
OS_EXT OS_TCB OSTCBTbl[OS_MAX_TASKS + OS_N_SYS_TASKS];
OS_EXT OS_TCB *OSTCBFreeList;
然后在OS_InitTCBList()鏈表初始化中:
view plaincopy to clipboardprint?
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
OS_TCB *ptcb1; /*創(chuàng)建兩個tcb指針*/
OS_TCB *ptcb2;
//指向全局變量
ptcb1 = &OSTCBTbl[0];
ptcb2 = &OSTCBTbl[1];
//利用OSTCBNext建立鏈表:
for (i = 0; i < (OS_MAX_TASKS + OS_N_SYS_TASKS - 1); i++) {
ptcb1->OSTCBNext = ptcb2;
ptcb1++;
ptcb2++;
}
OSTCBList = (OS_TCB *)0;
OSTCBFreeList = &OSTCBTbl[0]; //指向鏈頭
OS_TCB *ptcb1; /*創(chuàng)建兩個tcb指針*/
OS_TCB *ptcb2;
//指向全局變量
ptcb1 = &OSTCBTbl[0];
ptcb2 = &OSTCBTbl[1];
//利用OSTCBNext建立鏈表:
for (i = 0; i < (OS_MAX_TASKS + OS_N_SYS_TASKS - 1); i++) {
ptcb1->OSTCBNext = ptcb2;
ptcb1++;
ptcb2++;
}
OSTCBList = (OS_TCB *)0;
OSTCBFreeList = &OSTCBTbl[0]; //指向鏈頭
2.任務塊鏈表
在OSTaskCreate(...)創(chuàng)建任務時建立
view plaincopy to clipboardprint?
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
OSTaskCreate(void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT8U prio)
{
………
err = OS_TCBInit(prio, psp, (OS_STK *)0, 0, 0, (void *)0, 0);
}
INT8U OS_TCBInit (INT8U prio, OS_STK *ptos, OS_STK *pbos, INT16U id, INT32U stk_size, void *pext, INT16U opt)
{
…………
ptcb = OSTCBFreeList; /*獲取空任務鏈表頭*/
if (ptcb != (OS_TCB *)0) {
OSTCBFreeList = ptcb->OSTCBNext; /*空任務鏈表更新*/
OS_EXIT_CRITICAL();
ptcb->OSTCBStkPtr = ptos; /* 獲取棧*/
ptcb->OSTCBPrio = prio; /* 優(yōu)先級*/
ptcb->OSTCBStat = OS_STAT_RDY; /* 就緒狀態(tài)*/
ptcb->OSTCBPendTO = FALSE; /* Clear the Pend timeout flag */
ptcb->OSTCBDly = 0; /* Task is not delayed */
……..
OS_ENTER_CRITICAL();
OSTCBPrioTbl[prio] = ptcb;
ptcb->OSTCBNext = OSTCBList; /* Link into TCB chain */
ptcb->OSTCBPrev = (OS_TCB *)0;
if (OSTCBList != (OS_TCB *)0) {
OSTCBList->OSTCBPrev = ptcb;
}
OSTCBList = ptcb;
OSRdyGrp |= ptcb->OSTCBBitY; /* Make task ready to run */
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
OSTaskCtr++; /* Increment the #tasks counter */
OS_EXIT_CRITICAL();
return (OS_NO_ERR);
}
OSTaskCreate(void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT8U prio)
{
………
err = OS_TCBInit(prio, psp, (OS_STK *)0, 0, 0, (void *)0, 0);
}
INT8U OS_TCBInit (INT8U prio, OS_STK *ptos, OS_STK *pbos, INT16U id, INT32U stk_size, void *pext, INT16U opt)
{
…………
ptcb = OSTCBFreeList; /*獲取空任務鏈表頭*/
if (ptcb != (OS_TCB *)0) {
OSTCBFreeList = ptcb->OSTCBNext; /*空任務鏈表更新*/
OS_EXIT_CRITICAL();
ptcb->OSTCBStkPtr = ptos; /* 獲取棧*/
ptcb->OSTCBPrio = prio; /* 優(yōu)先級*/
ptcb->OSTCBStat = OS_STAT_RDY; /* 就緒狀態(tài)*/
ptcb->OSTCBPendTO = FALSE; /* Clear the Pend timeout flag */
ptcb->OSTCBDly = 0; /* Task is not delayed */
……..
OS_ENTER_CRITICAL();
OSTCBPrioTbl[prio] = ptcb;
ptcb->OSTCBNext = OSTCBList; /* Link into TCB chain */
ptcb->OSTCBPrev = (OS_TCB *)0;
if (OSTCBList != (OS_TCB *)0) {
OSTCBList->OSTCBPrev = ptcb;
}
OSTCBList = ptcb;
OSRdyGrp |= ptcb->OSTCBBitY; /* Make task ready to run */
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
OSTaskCtr++; /* Increment the #tasks counter */
OS_EXIT_CRITICAL();
return (OS_NO_ERR);
}
3.任務堆棧
注意和處理器堆棧不同一個概念
view plaincopy to clipboardprint?
INT8U OSTaskCreate (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT8U prio)
{
……..
psp = (OS_STK *)OSTaskStkInit(task, p_arg, ptos, 0);
/* Initialize the task's stack*/
}
INT8U OSTaskCreate (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT8U prio)
{
……..
psp = (OS_STK *)OSTaskStkInit(task, p_arg, ptos, 0);
/* Initialize the task's stack*/
}
堆棧類型
typedef unsigned int OS_STK;
創(chuàng)建任務時:
進入OSTaskStkInit函數:
view plaincopy to clipboardprint?
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
OS_STK *OSTaskStkInit(void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt)
{
unsigned int *stk;
opt = opt; /* 未用到的參數*/
stk = (unsigned int *)ptos; /* 裝載任務堆棧指針*/
/* 建立上下文*/
*--stk = (unsigned int) task; /* pc */
*--stk = (unsigned int) task; /* lr */
*--stk = 0; /* r12 */
*--stk = 0; /* r11 */
*--stk = 0; /* r10 */
*--stk = 0; /* r9 */
*--stk = 0; /* r8 */
*--stk = 0; /* r7 */
*--stk = 0; /* r6 */
*--stk = 0; /* r5 */
*--stk = 0; /* r4 */
*--stk = 0; /* r3 */
*--stk = 0; /* r2 */
*--stk = 0; /* r1 */
*--stk = (unsigned int) pdata; /* r0 */
*--stk = (SVC32MODE|0x0); /* cpsr IRQ, FIQ disable */
return ((void *)stk);
}
OS_STK *OSTaskStkInit(void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt)
{
unsigned int *stk;
opt = opt; /* 未用到的參數*/
stk = (unsigned int *)ptos; /* 裝載任務堆棧指針*/
/* 建立上下文*/
*--stk = (unsigned int) task; /* pc */
*--stk = (unsigned int) task; /* lr */
*--stk = 0; /* r12 */
*--stk = 0; /* r11 */
*--stk = 0; /* r10 */
*--stk = 0; /* r9 */
*--stk = 0; /* r8 */
*--stk = 0; /* r7 */
*--stk = 0; /* r6 */
*--stk = 0; /* r5 */
*--stk = 0; /* r4 */
*--stk = 0; /* r3 */
*--stk = 0; /* r2 */
*--stk = 0; /* r1 */
*--stk = (unsigned int) pdata; /* r0 */
*--stk = (SVC32MODE|0x0); /* cpsr IRQ, FIQ disable */
return ((void *)stk);
}
注意這個是移植時的底層代碼??!是將處理器中的寄存器存到任務堆棧,在SVC模式下
4.創(chuàng)建空閑任務和統(tǒng)計任務
這兩個任務在UCOS2里是默認創(chuàng)建,其中一個在OSInit中創(chuàng)建,另一個用戶可以在創(chuàng)建任務中調用OSStatInit()創(chuàng)建
空閑任務
OSInit中調用OS_InitTaskIdle();在OS_InitTaskIdle函數中創(chuàng)建了空閑任務:
(void)OSTaskCreate(OS_TaskIdle,
(void *)0,
&OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1],
OS_IDLE_PRIO); //優(yōu)先級別最低
然后看OS_TaskStat這個空任務做了什么:
void OS_TaskIdle (void *parg)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
cpu_sr = 0;
#endif
parg = parg;
for (;;) {
OS_ENTER_CRITICAL();
OSIdleCtr++; //計數
OS_EXIT_CRITICAL();
OSTaskIdleHook();
}
}
統(tǒng)計任務:
OSInit中調用OS_InitTaskStat();創(chuàng)建了統(tǒng)計任務,了解處理器利用率,優(yōu)先級比空閑高一級。
(void)OSTaskCreate(OS_TaskStat,
(void *)0,
&OSTaskStatStk[OS_TASK_STAT_STK_SIZE-1], OS_STAT_PRIO);
然后看OS_TaskStat任務,每秒計算一次處理器在單位時間內被使用的時間,公式
OSIdleCtr
OSCPUUsage = 100 * (1 - ----------------------------) (units are in %)
OSIdleCtrMax
通過統(tǒng)計空閑任務來知道目前處理器的占用率。