ucos 事件及事件控制块

1:任务间的同步

关于什么是同步直接copy一段文字解释:

其实上面说了俩种多任务之间的关系,1:多任务对同一个资源进行访问的时,必须进行共享资源之间的互斥操作。2:多个任务合作工作时,任务之间的先决条件。

2:事件

ucos中把用来通信的信号量,消息队列,消息邮箱都统一的看做为“事件”。
2.1 信号量
当信号量用来表示共享资源的数目的时候,此时的信号量为:计数新哈量。当信号量表示:互斥资源被占用的情况时为:互斥信号量或者为2值信号量。
2.2 消息邮箱


2.3:消息队列
将消息邮箱中的多个消息指针放入指针数组中,通过指针数组来传递数据的方法为:消息队列。跟消息邮箱比起来消息队列一次可以传递多个消息。

3:事件控制块

3.1 事件控制结构及初始化
前面说了,ucos中的事件指的就是:信号量,邮箱及消息队列。在多任务中,当一个任务等待一个资源或者等待某个条件满足的时候,ucso必须对此等待的任务进行标识及管理。ucos中对等待事件的任务使用与任务就绪表相同的记录处理方法。

ucos中事件控制块数据结构定义如下:

其中OSEventType指明事件的类型,其取值定义如下:

整个事件控制块如下图表示:

全局事件控制块的初始化代码如下:

上面的代码中的初始化过程与任务控制块一样的,同时定义了俩个全局比变量:

ucos系统默认定义了OS_MAX_EVENTS这么多个事件控制块,OSEventFreeList为一个单项链表。此时初始化的控制块没有与任何的具体事件相关联。
3.2 事件操作函数
事件操作函数由信号量,消息邮箱和队列操作函数调用。
A:事件控制块初始化函数
#if (OS_EVENT_EN)
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;
    }
}
#endif
初始化后的时间控制块结构如下:

同时函数OS_EventWaitListInit()被如:OSXXXCreate()的函数调用,其中XXX如下:
OSMutexCreate(),OSQ
Create(),OSSemCreate(),OSMoxCreate()。
B:使一个任务进入等待某事件的函数
#if (OS_EVENT_EN)
void  OS_EventTaskWait (OS_EVENT *pevent)
{
    INT8U  y;
    OSTCBCur->OSTCBEventPtr = pevent;      /* Store ptr to ECB in TCB         */
    /* Put task in waiting list  */
    pevent->OSEventTbl[OSTCBCur->OSTCBY] |= OSTCBCur->OSTCBBitX;
    pevent->OSEventGrp   |= OSTCBCur->OSTCBBitY;
    y             =  OSTCBCur->OSTCBY;        /* Task no longer ready          */
    OSRdyTbl[y]  &= ~OSTCBCur->OSTCBBitX;
    if (OSRdyTbl[y] == 0) {
      /* Clear event grnlp bit if this was oy task pending */
     OSRdyGrp &= ~OSTCBCur->OSTCBBitY

   }
}
#endif
其上面的函数的操作过程与任务的挂起即使任务从任务就绪表中移除是相同的,函数OS_EventTaskWait()是被如下函数所调用:OSXXXPend().
C:使一个等待事件的任务进入就绪状态
等待某事件的任务具备了可运行的条件时,就使此任务进入就绪状态。这时要调用函数OS_EventTaskRdy(),此函数作用就是使调用此函数的任务在事件等待表中清零(解除等待状态),再使此任务进入就绪状态。同时函数OS_EventTaskRdy()是在如:OSXXXPost()函数中调用。

上面的函数:首先在事件等待表中取出等待此事件最高的优先级prio,根据prio取得任务的TCB,如果此任务prio没有挂起的话,使任务进入就绪状态,同时移除任务的等待事件。
/*
***********************************************************************************
*                 REMOVE TASK FROM EVENT WAIT LIST
*
* Description: Remove a task from an event's wait list.
*
* Arguments  : ptcb     is a pointer to the task to remove.
*
*              pevent   is a pointer to the event control block.
*
* Returns    : none
*
* Note       : This function is INTERNAL to uC/OS-II and your application should not call it.
*********************************************************************************
*/
#if (OS_EVENT_EN)
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;
    }
}


版权声明:本文为suiyuan19840208原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。