再读 ucosII源码(邵贝贝):内核结构--任务控制块(Task Control Blocks, OS_TCB)

此文,供
再读 ucosII源码(邵贝贝):内核结构
使用。

OS_TCB定义:

一旦任务建立了,任务控制块OS_TCB将被赋值。任务控制块是一个数据结构。
当任务的CPU使用权被剥夺时,μC/OS-Ⅱ用它来保存该任务的状态。
当任务重新得到CPU使用权时,任务控制块能确保任务从当时被中断的那一点丝毫不差地继续执行。
OS_TCB全部驻留在RAM中。
OS_TCB源码结构如下:


/*$PAGE*/
/*
*********************************************************************************************************
*                                          TASK CONTROL BLOCK
*********************************************************************************************************
*/

typedef struct os_tcb {
    OS_STK          *OSTCBStkPtr;           /* Pointer to current top of stack                         */

#if OS_TASK_CREATE_EXT_EN > 0
    void            *OSTCBExtPtr;           /* Pointer to user definable data for TCB extension        */
    OS_STK          *OSTCBStkBottom;        /* Pointer to bottom of stack                              */
    INT32U           OSTCBStkSize;          /* Size of task stack (in number of stack elements)        */
    INT16U           OSTCBOpt;              /* Task options as passed by OSTaskCreateExt()             */
    INT16U           OSTCBId;               /* Task ID (0..65535)                                      */
#endif

    struct os_tcb   *OSTCBNext;             /* Pointer to next     TCB in the TCB list                 */
    struct os_tcb   *OSTCBPrev;             /* Pointer to previous TCB in the TCB list                 */

#if (OS_EVENT_EN) || (OS_FLAG_EN > 0)
    OS_EVENT        *OSTCBEventPtr;         /* Pointer to          event control block                 */
#endif

#if (OS_EVENT_EN) && (OS_EVENT_MULTI_EN > 0)
    OS_EVENT       **OSTCBEventMultiPtr;    /* Pointer to multiple event control blocks                */
#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_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;              /* Nbr ticks to delay task or, timeout waiting for event   */
    INT8U            OSTCBStat;             /* Task      status                                        */
    INT8U            OSTCBStatPend;         /* Task PEND status                                        */
    INT8U            OSTCBPrio;             /* Task priority (0 == highest)                            */

    INT8U            OSTCBX;                /* Bit position in group  corresponding to task priority   */
    INT8U            OSTCBY;                /* Index into ready table corresponding to task priority   */
#if OS_LOWEST_PRIO <= 63
    INT8U            OSTCBBitX;             /* Bit mask to access bit position in ready table          */
    INT8U            OSTCBBitY;             /* Bit mask to access bit position in ready group          */
#else
    INT16U           OSTCBBitX;             /* Bit mask to access bit position in ready table          */
    INT16U           OSTCBBitY;             /* Bit mask to access bit position in ready group          */
#endif

#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
    INT8U            OSTCBTaskName[OS_TASK_NAME_SIZE];
#endif
} OS_TCB;

.OSTCBStkPtr:

是指向当前任务栈顶的指针。μC/OS-Ⅱ允许每个任务有自己的栈,尤为重要的是,每个任务的栈的容量可以是任意的。有些商业内核要求所有任务栈的容量都一样,除非用户写一个复杂的接口函数来改变之。这种限制浪费了RAM,当各任务需要的栈空间不同时,也得按任务中预期栈容量需求最多的来分配栈空间。OSTCBStkPtr是OS_TCB数据结构中唯一的一个能用汇编语言来处置的变量(在任务切换段的代码Context-switching code之中,)把OSTCBStkPtr放在数据结构的最前面,使得从汇编语言中处理这个变量时较为容易。

.OSTCBExtPtr:

指向用户定义的任务控制块扩展。用户可以扩展任务控制块而不必修改μC/OS-Ⅱ的源代码。.OSTCBExtPtr只在函数OstaskCreateExt()中使用,故使用时要将OS_TASK_CREAT_EN设为1,以允许建立任务函数的扩展。例如用户可以建立一个数据结构,这个数据结构包含每个任务的名字,或跟踪某个任务的执行时间,或者跟踪切换到某个任务的次数(见例3)。注意,笔者将这个扩展指针变量放在紧跟着堆栈指针的位置,为的是当用户需要在汇编语言中处理这个变量时,从数据结构的头上算偏移量比较方便。

typedef struct {
    char    TaskName[30];   //任务名称
    INT16U  TaskCtr;//
    INT16U  TaskExecTime;//某个任务执行时间
    INT32U  TaskTotExecTime;//切换到某个任务的次数
} TASK_USER_DATA;
    OSTaskCreateExt(TaskStart,
                    (void *)0,
                    &TaskStartStk[TASK_STK_SIZE-1],
                    TASK_START_PRIO,
                    TASK_START_ID,
                    &TaskStartStk[0],
                    TASK_STK_SIZE,
                    &TaskUserData[TASK_START_ID],
                    0); 

.OSTCBStkBottom:

是指向任务栈底的指针。如果微处理器的栈指针是递减的,即栈存储器从高地址向低地址方向分配,则OSTCBStkBottom指向任务使用的栈空间的最低地址。类似地,如果微处理器的栈是从低地址向高地址递增型的,则OSTCBStkBottom指向任务可以使用的栈空间的最高地址。函数OSTaskStkChk()要用到变量OSTCBStkBottom,在运行中检验栈空间的使用情况。用户可以用它来确定任务实际需要的栈空间。这个功能只有当用户在任务建立时允许使用OSTaskCreateExt()函数时才能实现。这就要求用户将OS_TASK_CREATE_EXT_EN设为1,以便允许该功能。

.OSTCBStkSize:

存有栈中可容纳的指针元数目而不是用字节(Byte)表示的栈容量总数。也就是说,如果栈中可以保存1,000个入口地址,每个地址宽度是32位的,则实际栈容量是4,000字节。同样是1,000个入口地址,如果每个地址宽度是16位的,则总栈容量只有2,000字节。在函数OSStakChk()中要调用OSTCBStkSize。同理,若使用该函数的话,要将OS_TASK_CREAT_EXT_EN设为1。
栈的类型:

typedef unsigned int   OS_STK;                   /* Each stack entry is 32-bit wide                    */

.OSTCBOpt

把“选择项”传给OSTaskCreateExt(),只有在用户将OS_TASK_CREATE_EXT_EN设为1时,这个变量才有效。μC/OS-Ⅱ目前只支持3个选择项(见uCOS_II.H):OS_TASK_OTP_STK_CHK, OS_TASK_OPT_STK_CLR和OS_TASK_OPT_SAVE_FP。 OS_TASK_OTP_STK_CHK 用于告知TaskCreateExt(),在任务建立的时候任务栈检验功能得到了允许。OS_TASK_OPT_STK_CLR表示任务建立的时候任务栈要清零。只有在用户需要有栈检验功能时,才需要将栈清零。如果不定义OS_TASK_OPT_STK_CLR,而后又建立、删除了任务,栈检验功能报告的栈使用情况将是错误的。如果任务一旦建立就决不会被删除,而用户初始化时,已将RAM清过零,则OS_TASK_OPT_STK_CLR不需要再定义,这可以节约程序执行时间。传递了OS_TASK_OPT_STK_CLR将增加TaskCreateExt()函数的执行时间,因为要将栈空间清零。栈容量越大,清零花的时间越长。最后一个选择项OS_TASK_OPT_SAVE_FP通知TaskCreateExt(),任务要做浮点运算。如果微处理器有硬件的浮点协处理器,则所建立的任务在做任务调度切换时,浮点寄存器的内容要保存。

.OSTCBId

用于存储任务的识别码。这个变量现在没有使用,留给将来扩展用。

.OSTCBNext和.OSTCBPrev

用于任务控制块OS_TCBs的双重链接,该链表在时钟节拍函数OSTimeTick()中使用,用于刷新各个任务的任务延迟变量.OSTCBDly,每个任务的任务控制块OS_TCB在任务建立的时候被链接到链表中,在任务删除的时候从链表中被删除。双重连接的链表使得任一成员都能被快速插入或删除。

.OSTCBEventPtr

是指向事件控制块的指针

.OSTCBMsg

是指向传给任务的消息的指针

.OSTCBDly

当需要把任务延时若干时钟节拍时要用到这个变量,或者需要把任务挂起一段时间以等待某事件的发生,这种等待是有超时限制的。在这种情况下,这个变量保存的是任务允许等待事件发生的最多时钟节拍数。如果这个变量为0,表示任务不延时,或者表示等待事件发生的时间没有限制。

.OSTCBStat

是任务的状态字。当.OSTCBStat为0,任务进入就绪态。可以给.OSTCBStat赋其它的值,在文件uCOS_II.H中有关于这个值的描述。

.OSTCBPrio

是任务优先级。高优先级任务的.OSTCBPrio值小。也就是说,这个值越小,任务的优先级越高。

.OSTCBX, .OSTCBY, .OSTCBBitX和 .OSTCBBitY

用于加速任务进入就绪态的过程或进入等待事件发生状态的过程(避免在运行中去计算这些值)。这些值是在任务建立时算好的,或者是在改变任务优先级时算出的。
服务于任务就绪表的操作(添加任务、删除任务、查找任务),
参见: uCOS 就绪表实现方法解析

.OSTCBDelReq

是一个布尔量,用于表示该任务是否需要删除

OSTCBTbl[],OSTCBFreeList,任务控制块数组的组织

应用程序中可以有的最多任务数(OS_MAX_TASKS)是在文件OS_CFG.H中定义的。这个最多任务数也是μC/OS-Ⅱ分配给用户程序的最多任务控制块OS_TCBs的数目。将OS_MAX_TASKS的数目设置为用户应用程序实际需要的任务数可以减小RAM的需求量。所有的任务控制块OS_TCBs都是放在任务控制块列表数组OSTCBTbl[]中的。请注意,μC/OS-Ⅱ分配给系统任务OS_N_SYS_TASKS若干个任务控制块,见文件μC/OS-Ⅱ.H,供其内部使用。目前,一个用于空闲任务,另一个用于任务统计(如果OS_TASK_STAT_EN是设为1的)。在μC/OS-Ⅱ初始化的时候,如图3.2所示,所有任务控制块OS_TCBs被链接成单向空任务链表。当任务一旦建立,空任务控制块指针OSTCBFreeList指向的任务控制块便赋给了该任务,然后OSTCBFreeList的值调整为指向下链表中下一个空的任务控制块。一旦任务被删除,任务控制块就还给空任务链表。
这里写图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值