ucos-II 采用了事件控制块(ECB)的机制完成任务与任务、中断与任务之间的交互。并在此基础上扩展实现了信号量、互斥信号量、消息邮箱和消息队列。理解ucos-II的ECB主要看以下几方面的代码(包含在core.c中):
1. EVENT的定义:
typedef struct { INT8U OSEventType; //事件控制块类型(见OS_EVENT_TYPE) INT8U OSEventGrp; //事件群体响应去等待任务事件发生 INT16U OSEventCnt; //信号量,在其它事件中不用 void *OSEventPtr; //消息或者队列结构指针 INT8U OSEventTbl[OS_EVENT_TBL_SIZE]; //任务列表等待事件发生 } OS_EVENT;
其中OSEventType中包括:
#define OS_EVENT_TYPE_UNUSED 0 #define OS_EVENT_TYPE_MBOX 1 #define OS_EVENT_TYPE_Q 2 #define OS_EVENT_TYPE_SEM 3 #define OS_EVENT_TYPE_MUTEX 4 #define OS_EVENT_TYPE_FLAG 5
结构体中成员OSEventGrp和OSEventTbl,其结构体和使用机制与任务调度中是一样的。
2.ECB的全局变量
ECB在初始阶段初始化两个全局变量,以维护一个EVENT资源的队列。
OS_EXT OS_EVENT *OSEventFreeList; /* Pointer to list of free EVENT control blocks */ OS_EXT OS_EVENT OSEventTbl[OS_MAX_EVENTS];/* Table of EVENT control blocks */
3.ECB的核心函数
- 首先调用OSEventFreeList获取一个Event资源,然后通过OS_EventWaitListInit初始化,主要是初始化Event变量中的OSEventGrp和OSEventTbl两个成员变量;
- 当外部的XXPend函数被调用时(此时调用XXPend的任务已将自己的状态设置为XX_PEND等待挂起),此时调用OS_EventTaskWait,该准备被挂起的任务通过更新OSEventGrp和OSEventTbl两个成员变量记录下来;
- 当外部的XXPost函数被调用后,执行OS_EventTaskRdy。
例如:OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM),此时pevent中的最高优先级任务被选择出来,通过置反取与完成状态清回OS_STAT_RDY,因为OS_STAT_RDY的值是0x00。然后该任务会被更新至全局就绪表等待被选择调度。
ptcb->OSTCBStat &= ~msk; //事件状态位清除 if (ptcb->OSTCBStat == OS_STAT_RDY) { //如果任务就绪,(不能被挂起) OSRdyGrp |= bity; /* Put task in the ready to run list */ OSRdyTbl[y] |= bitx; }