μc/OS 任务管理
2.1 任务管理数据结构
任务控制块、任务空闲链表和任务就绪链表、任务优先级指针表、任务堆栈等。
2.1.1 任务控制块
OSTCB
结构体包含了任务控制信息。
typedef struct os_tcb {
OS_STK *OSTCBStkPtr; /* Pointer to current top of stack */
#if OS_TASK_CREATE_EXT_EN > 0u
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_TASK_CREATE_EXT_EN > 0u
#if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u)
OS_TLS OSTCBTLSTbl[OS_TLS_TBL_SIZE];
#endif
#endif
#if (OS_EVENT_EN)
OS_EVENT *OSTCBEventPtr; /* Pointer to event control block */
#endif
#if (OS_EVENT_EN) && (OS_EVENT_MULTI_EN > 0u)
OS_EVENT **OSTCBEventMultiPtr; /* Pointer to multiple event control blocks */
#endif
#if ((OS_Q_EN > 0u) && (OS_MAX_QS > 0u)) || (OS_MBOX_EN > 0u)
void *OSTCBMsg; /* Message received from OSMboxPost() or OSQPost() */
#endif
#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u)
#if OS_TASK_DEL_EN > 0u
OS_FLAG_NODE *OSTCBFlagNode; /* Pointer to event flag node */
#endif
OS_FLAGS OSTCBFlagsRdy; /* Event flags that made task ready to run */
#endif
INT32U 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 */
OS_PRIO OSTCBBitX; /* Bit mask to access bit position in ready table */
OS_PRIO OSTCBBitY; /* Bit mask to access bit position in ready group */
#if OS_TASK_DEL_EN > 0u
INT8U OSTCBDelReq; /* Indicates whether a task needs to delete itself */
#endif
#if OS_TASK_PROFILE_EN > 0u
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_EN > 0u
INT8U *OSTCBTaskName;
#endif
#if OS_TASK_REG_TBL_SIZE > 0u
INT32U OSTCBRegTbl[OS_TASK_REG_TBL_SIZE];
#endif
} OS_TCB;
OSTCBPrio
,每个任务有唯一的优先级,用户任务的优先级为0~61,62和63倍统计任务和空闲任务占用。
μc/OS是以结构体数组的形式生成任务控制块的实体。
OS_TCB OSTCBTbl[OS_MAX_TASKS + OS_N_SYS_TASKS];
结构体数组OSTCBTbl
中元素的个数为最大用户数量+系统任务数。
2.1.2 空闲链表和就绪链表
μc/OS将任务控制块分成两个链表来管理,即空闲任务链表和就绪任务链表。所谓空闲任务控制块,是指未分配给某个任务的任务控制块,创建一个新任务的前提就是系统中有这样的空闲任务块。就绪链表则是将所有的就绪任务栓在一起,如果有新的任务就绪,就要将其任务控制块从空闲链表中取出,加入到就绪链表中。
OS_TCB *OSTCBFreeList; //空闲链表
OS_TCB *OSTCBList; //就绪链表
OSTCBTbl中的任务控制块为空闲链表和就绪链表的节点元素,其中的prev、next指针指向其在OSTCBFreeList或OSTCBList中的下一个或者前一个节点。当创建一个任务的时候,就在空闲链表中remove一个元素,然后为其赋值,再将该元素插入就绪链表。将一个TCB从空闲链表插入到就绪链表时,是从OSTCBFreeList的表头取出一个元素,插入OSTCBList的表头。即,OSTCBFreeList永远指向空闲链表的表头,OSTCBList永远指向就绪链表的表头。
2.1.3 任务优先级指针表
即任务优先级指针数组,用来获某优先级的任务的任务控制块地址。
OS_TCB *OSTCBPrioTbl[OS_LOWEST_PRIO + 1]
任务优先级指针数组的元素为指向OS_TCB
的指针。可以快速地根据优先级访问对应任务控制块的内容。
2.1.4 任务堆栈
为了满足任务切换或者响应中断时保存CPU寄存器的内容,以及存储任务私有数据的需要,每个任务都有自己的堆栈。
#define TASK_STK_SIZE 512
typedef unsigned int OS_STK;
OS_STK TaskStk[OS_MAX_TASKS][TASK_STK_SIZE];
TaskStk
中的元素类型为OS_STK
,在32位PC系统中为32位无符号数。这里定义了最多用户任务数个用户堆栈,每个用户堆栈的大小为TASK_STK_SIZE
。统计任务和空闲任务的堆栈是单独定义的,分别是OSTaskStatStk
和OSTaskIdleStk
。它们作为全局变量定义在ucos_ii.h
中。任务堆栈可以由用户自己定义。
OS_EXT OS_STK OSTaskStatStk[OS_TASK_STAT_STK_SIZE]