ucos-ii内核探究1 任务的数据结构和创建

移植好后,应该多看内核源码了!我比较喜欢看里面的实现过程,有些算法很巧妙,“知其然且知其所以然”,不理解原理不能谓之掌握。

 

任务

首先看她定义的数据结构吧!

 

任务控制块tcb

         UCOS-II.H中定义了tcb结构:typedef struct os_tcb { /*指向任务堆栈栈顶的指针*/ OS_STK *OSTCBStkPtr; #if OS_TASK_CREATE_EXT_EN > 0 /*指向任务控制块扩展的指针*/ void *OSTCBExtPtr; /*指向任务堆栈栈底的指针*/ OS_STK *OSTCBStkBottom; /*任务堆栈的长度*/ INT32U OSTCBStkSize; /*创建任务时的选择项*/ 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; /*任务的当前状态标志*/ INT8U OSTCBStat; BOOLEAN OSTCBPendTO; /* Flag indicating PEND timed out (TRUE == timed out) */ /*任务的优先级别*/ 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()建立并初始化

OSInit() { ……… OS_InitTCBList(); //TCB链表初始化 ……… }

 

 

OS_InitTCBList():

TCB创建步骤:建立全局变量OSTCBTb1[]

 

#define OS_EXT extern OS_EXT OS_TCB OSTCBTbl[OS_MAX_TASKS + OS_N_SYS_TASKS]; OS_EXT OS_TCB *OSTCBFreeList; 然后在OS_InitTCBList()链表初始化中:

OS_TCB *ptcb1; /*创建两个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(...)创建任务时建立

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; /* 优先级*/ ptcb->OSTCBStat = OS_STAT_RDY; /* 就绪状态*/ 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.任务堆栈

注意和处理器堆栈不同一个概念

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;

                   创建任务时:

 

 

进入OSTaskStkInit函数:

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.创建空闲任务和统计任务

这两个任务在UCOS2里是默认创建,其中一个在OSInit中创建,另一个用户可以在创建任务中调用OSStatInit()创建

空闲任务

                   OSInit中调用OS_InitTaskIdle();OS_InitTaskIdle函数中创建了空闲任务:

                  (void)OSTaskCreate(OS_TaskIdle,

                       (void *)0,

                       &OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1],

                       OS_IDLE_PRIO);                   //优先级别最低

然后看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();           

    }

}

     统计任务:

     OSInit中调用OS_InitTaskStat();创建了统计任务,了解处理器利用率,优先级比空闲高一级。

(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

         通过统计空闲任务来知道目前处理器的占用率。

 

你可能感兴趣的:(数据结构,struct,OS,ext,Access,任务)