前面总结了UCOSII下的任务调度以及任务间的同步与通信机制,这篇文章简单总结下UCOSII下的三大控制块:TCB(任务控制块)、ECB(事件控制块)以及MCB(内存控制块)
UCOSII初始化时建立的五大缓冲区(以单链表的形式存在):
若当使用相应控制块时则向缓冲区申请,不使用时释放回缓冲区,若缓冲区中的相应控制块使用完了,则不能再分配相应控制块。在初始化时可配置缓冲区大小
TCB(Task_Control_Block)任务控制块:
/*
*********************************************************************************************************
* TASK CONTROL BLOCK
*********************************************************************************************************
*/
typedef struct os_tcb {
OS_STK *OSTCBStkPtr; /* 当前任务的栈顶地址(UCOSII中每个任务都有自己的栈)且容量任意 */
#if OS_TASK_CREATE_EXT_EN > 0
void *OSTCBExtPtr; /*只在OstaskCreateExt()函数中使用,用于用户扩展任务控制*/
OS_STK *OSTCBStkBottom; /* 指向任务可以使用的栈空间的最高地址,一般在OSTaskStkChk()函数中使用 */
INT32U OSTCBStkSize; /*存有栈中可容纳的指针数目,在OSTaskStkChk()函数中使用*/
INT16U OSTCBOpt; /* 将选项传递给OstaskCreateExt()函数 */
INT16U OSTCBId; /* Task ID (0..65535)用于存储任务识别码,暂无用,留作扩展 */
#endif
struct os_tcb *OSTCBNext; /* TCB链表下一个任务对应的TCB块,在OSTimeTick()函数中被调用,用于刷新任务延迟变量OSTCBDly */
struct os_tcb *OSTCBPrev; /* 与上面类似(每个任务在创建时都将被加入TCB链表中) */
#if (OS_EVENT_EN) || (OS_FLAG_EN > 0)
OS_EVENT *OSTCBEventPtr; /* 指向事件控制块的指针 */
#endif
#if (OS_EVENT_EN) && (OS_EVENT_MULTI_EN > 0)
OS_EVENT **OSTCBEventMultiPtr; /* 指向多事件控制块的指针 */
#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; /* 指向 事件标志节点 */
#endif
OS_FLAGS OSTCBFlagsRdy; /* 使得任务准备运行(进入就绪态的事件标志)的标志 */
#endif
INT16U OSTCBDly; /* 任务等待(挂起)时限,对应各种pend函数 */
INT8U OSTCBStat; /* 任务状态,0:就绪,1:等待(挂起)信号量状态,2:等待(挂起)消息邮箱状态,3:等待(挂起)消息队列状态,4:Suspend(挂起)状态(此挂起只有Resume可解),5:等待(挂起)互斥信号量状态 */
INT8U OSTCBStatPend; /* 等状态的状态标志,0:等待状态OK,非等待状态或等待完成状态,1:等待超时状态,2:等待中止状态 */
INT8U OSTCBPrio; /* 储存任务优先级(0 == highest) */
INT8U OSTCBX; /* 任务优先级计算参数,优先级低3位对应的数值,即prio & 0x07 */
INT8U OSTCBY; /* 任务优先级高3位对应的值,即prio >> 3(存有疑问?) */
#if OS_LOWEST_PRIO <= 63
INT8U OSTCBBitX; /* 对应就绪表组的值,OSRdyTbl[OSTCBY] |= OSTCBBitX */
INT8U OSTCBBitY; /* 就绪表组OSRdyGrp |= OSTCBBitY 即上行所提到的对应组 */
#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; /* 标识该任务十分需要被删除 */
#endif
#if OS_TASK_PROFILE_EN > 0
INT32U OSTCBCtxSwCtr; /* 表示任务被调用的次数 */
INT32U OSTCBCyclesTot; /* 该任务运行的节拍总数 */
INT32U OSTCBCyclesStart; /* 该任务恢复开始时的节拍数 */
OS_STK *OSTCBStkBase; /* 该任务堆栈的开始位置 */
INT32U OSTCBStkUsed; /* 该任务堆栈已被使用的字节数 */
#endif
#if OS_TASK_NAME_SIZE > 1
INT8U OSTCBTaskName[OS_TASK_NAME_SIZE];/* 该任务的名称 */
#endif
} OS_TCB;
ECB(Event_Control_Block)事件控制块:
/*
*********************************************************************************************************
* EVENT CONTROL BLOCK
*********************************************************************************************************
*/
#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0)
typedef struct os_event {
INT8U OSEventType; /*事件控制块的类型(OS_EVENT_TYPE_UNUSED(未使用)、OS_EVENT_TYPE_MBOX、OS_EVENT_TYPE_Q、OS_EVENT_TYPE_SEM、OS_EVENT_TYPE_MUTEX和OS_EVENT_TYPE_FLAG) */
void *OSEventPtr; /* 指向消息或消息队列中消息结构体的指针,只在邮箱和消息队列事件中存在 */
INT16U OSEventCnt; /* 当事件类型为信号量时的计数器 */
#if OS_LOWEST_PRIO <= 63
INT8U OSEventGrp; /* 等待某事件的任务表组 */
INT8U OSEventTbl[OS_EVENT_TBL_SIZE]; /* 等待某事件的任务表 */
#else
INT16U OSEventGrp; /* Group corresponding to tasks waiting for event to occur */
INT16U OSEventTbl[OS_EVENT_TBL_SIZE]; /* List of tasks waiting for event to occur */
#endif
#if OS_EVENT_NAME_SIZE > 1
INT8U OSEventName[OS_EVENT_NAME_SIZE];/* 事件名 */
#endif
} OS_EVENT;
#endif
MCB(Memory_Control_Block)事件控制块:
/*
*********************************************************************************************************
* MEMORY PARTITION DATA STRUCTURES
*********************************************************************************************************
*/
#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0)
typedef struct os_mem { /* MEMORY CONTROL BLOCK */
void *OSMemAddr; /* 内存分区的首地址 */
void *OSMemFreeList; /* 内存控制块组成的链表头地址 */
INT32U OSMemBlkSize; /* 每个内存控制块的大小(字节) */
INT32U OSMemNBlks; /* 内存分区中内存控制块的数目 */
INT32U OSMemNFree; /* 内存分区中空闲内存控制块的数目 */
#if OS_MEM_NAME_SIZE > 1
INT8U OSMemName[OS_MEM_NAME_SIZE]; /* 内存分区的名字 */
#endif
} OS_MEM;
typedef struct os_mem_data {
void *OSAddr; /* Pointer to the beginning address of the memory partition */
void *OSFreeList; /* Pointer to the beginning of the free list of memory blocks */
INT32U OSBlkSize; /* Size (in bytes) of each memory block */
INT32U OSNBlks; /* Total number of blocks in the partition */
INT32U OSNFree; /* Number of memory blocks free */
INT32U OSNUsed; /* Number of memory blocks used */
} OS_MEM_DATA;
#endif