您的位置:首页 > 其它

uc/os-ii事件控制块

2015-07-02 16:21 176 查看
任务间的同步依赖于任务间的通信。在μC/OS-II中,使用信号量、互斥信号量、消息邮箱、消息队列、事件标志组这些被称作事件的中间环节来实现任务之间的通信的。为了把描述事件的数据结构统一起来,μC/OS-II使用叫做事件控制块ECB的数据结构来描述诸如信号量、互斥信号量、消息邮箱、消息队列、事件标志组这些事件。

事件控制块中包含包括等待任务表在内的所有有关事件的数据 。

#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0)
typedef struct os_event {
INT8U    OSEventType;                    /* Type of event control block (see OS_EVENT_TYPE_xxxx)    */
void    *OSEventPtr;                     /* Pointer to message or queue structure                   */
INT16U   OSEventCnt;                     /* Semaphore Count (not used if other EVENT type)          */
#if OS_LOWEST_PRIO <= 63
INT8U    OSEventGrp;                     /* Group corresponding to tasks waiting for event to occur */
INT8U    OSEventTbl[OS_EVENT_TBL_SIZE];  /* List of tasks waiting for event to occur                */
#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;


图示为事件控制块的内存结构图。


一般地,对于事件控制块进行如下一些通用操作:

OS_EventWaitListInit():初始化事件控制块。

初始化等待任务列表为全0,没有任务在等待事件。

void  OS_EventWaitListInit (OS_EVENT *pevent)
{
#if OS_LOWEST_PRIO <= 63
INT8U  *ptbl;
#else
INT16U *ptbl;
#endif
INT8U   i;

pevent->OSEventGrp = 0;                      /* No task waiting on event                           */
ptbl               = &pevent->OSEventTbl[0];

for (i = 0; i < OS_EVENT_TBL_SIZE; i++) {
*ptbl++ = 0;
}
}


OS_EventTaskRdy():使任务进入就绪态。

当某个事件发生后,就要使等待任务列表中优先级最高的任务脱离等待,并置于就绪状态。

INT8U  OS_EventTaskRdy (OS_EVENT *pevent, void *pmsg, INT8U msk, INT8U pend_stat)
{
OS_TCB  *ptcb;
INT8U    y;
INT8U    x;
INT8U    prio;
#if OS_LOWEST_PRIO > 63
INT16U  *ptbl;
#endif

#if OS_LOWEST_PRIO <= 63
y    = OSUnMapTbl[pevent->OSEventGrp];              /* Find HPT waiting for message                */
x    = OSUnMapTbl[pevent->OSEventTbl[y]];
prio = (INT8U)((y << 3) + x);                       /* Find priority of task getting the msg       */
#else
if ((pevent->OSEventGrp & 0xFF) != 0) {             /* Find HPT waiting for message                */
y = OSUnMapTbl[ pevent->OSEventGrp & 0xFF];
} else {
y = OSUnMapTbl[(pevent->OSEventGrp >> 8) & 0xFF] + 8;
}
ptbl = &pevent->OSEventTbl[y];
if ((*ptbl & 0xFF) != 0) {
x = OSUnMapTbl[*ptbl & 0xFF];
} else {
x = OSUnMapTbl[(*ptbl >> 8) & 0xFF] + 8;
}
prio = (INT8U)((y << 4) + x);                       /* Find priority of task getting the msg       */
#endif

ptcb                  =  OSTCBPrioTbl[prio];        /* Point to this task's OS_TCB                 */
ptcb->OSTCBDly        =  0;                         /* Prevent OSTimeTick() from readying task     */
#if ((OS_Q_EN > 0) && (OS_MAX_QS > 0)) || (OS_MBOX_EN > 0)
ptcb->OSTCBMsg        =  pmsg;                      /* Send message directly to waiting task       */
#else
pmsg                  =  pmsg;                      /* Prevent compiler warning if not used        */
#endif
ptcb->OSTCBStat      &= ~msk;                       /* Clear bit associated with event type        */
ptcb->OSTCBStatPend   =  pend_stat;                 /* Set pend status of post or abort            */
/* See if task is ready (could be susp'd)      */
if ((ptcb->OSTCBStat &   OS_STAT_SUSPEND) == OS_STAT_RDY) {
OSRdyGrp         |=  ptcb->OSTCBBitY;           /* Put task in the ready to run list           */
OSRdyTbl[y]      |=  ptcb->OSTCBBitX;
}

OS_EventTaskRemove(ptcb, pevent);                   /* Remove this task from event   wait list     */
#if (OS_EVENT_MULTI_EN > 0)
if (ptcb->OSTCBEventMultiPtr != (OS_EVENT **)0) {   /* Remove this task from events' wait lists    */
OS_EventTaskRemoveMulti(ptcb, ptcb->OSTCBEventMultiPtr);
ptcb->OSTCBEventPtr       = (OS_EVENT  *)pevent;/* Return event as first multi-pend event ready*/
}
#endif

return (prio);
}


OS_EventTaskWait():使任务进入等待某事件发生状态

当某个任务要等待一个事件发生时,相应OSSemPend()、OSMutexPend()、OSMboxPend()或OSQPend()函数会调用OSEventTaskWait()函数将当前任务从任务就绪表中删除,并放到相应事件的事件控制块的等待任务列表中。

void  OS_EventTaskWait (OS_EVENT *pevent)
{
INT8U  y;
OSTCBCur->OSTCBEventPtr               = pevent;                 /* Store ptr to ECB in TCB         */

pevent->OSEventTbl[OSTCBCur->OSTCBY] |= OSTCBCur->OSTCBBitX;    /* Put task in waiting list        */
pevent->OSEventGrp                   |= OSTCBCur->OSTCBBitY;

y             =  OSTCBCur->OSTCBY;            /* Task no longer ready                              */
OSRdyTbl[y]  &= ~OSTCBCur->OSTCBBitX;
if (OSRdyTbl[y] == 0) {
OSRdyGrp &= ~OSTCBCur->OSTCBBitY;         /* Clear event grp bit if this was only task pending */
}
}


OS_EventTaskRemove() : 删除任务对某时间的等待状态

void  OS_EventTaskRemove (OS_TCB   *ptcb,
OS_EVENT *pevent)
{
INT8U  y;
y                       =  ptcb->OSTCBY;
pevent->OSEventTbl[y]  &= ~ptcb->OSTCBBitX;         /* Remove task from wait list                  */
if (pevent->OSEventTbl[y] == 0) {
pevent->OSEventGrp &= ~ptcb->OSTCBBitY;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: