uC/OS II--与ECB操作相关的四个函数

来源:互联网 发布:windows 10 卡屏司机 编辑:程序博客网 时间:2024/05/16 04:36

对ECB的操作一般包括:
    * 初始化一个事件控制块               (void  OS_EventWaitListInit (OS_EVENT *pevent))
    * 使一个任务进入就绪态               (INT8U OS_EventTaskRdy (OS_EVENT *pevent, void *msg, INT8U msk))
    * 使一个任务进入等待某事件的状态     (void  OS_EventTaskWait (OS_EVENT *pevent))
    * 因为等待超时而使一个任务进入就绪态 (void  OS_EventTO (OS_EVENT *pevent))

    对OS_EventTaskRdy()函数和OS_EventTO函数的调用都需要关中断

1. OS_EventWaitListInit (OS_EVENT *pevent)
    此函数被与ECB建立相关的函数调用,如OSSemCreate()、OSMutexCreate()、OSQCreate()和OSMboxCreate()。函数功能就是对ECB中的等待任务列表进行初始化,函数创建时,等待任务列表初始化为空。这个函数是对内的,即此函数可以被uC/OS II调用,用户应用程序不可以直接调用此函数。代码如下:

#if ((OS_Q_EN > 0) && (OS_MAX_QS > 0)) || (OS_MBOX_EN > 0) || (OS_SEM_EN > 0) || (OS_MUTEX_EN > 0)
void  OS_EventWaitListInit (OS_EVENT *pevent)
{
    INT8U  *ptbl;

    pevent->OSEventGrp = 0x00;                  
    ptbl               = &pevent->OSEventTbl[0];

#if OS_EVENT_TBL_SIZE > 0
    *ptbl++            = 0x00;
#endif

#if OS_EVENT_TBL_SIZE > 1
    *ptbl++            = 0x00;
#endif

#if OS_EVENT_TBL_SIZE > 2
    *ptbl++            = 0x00;
#endif

#if OS_EVENT_TBL_SIZE > 3
    *ptbl++            = 0x00;
#endif

#if OS_EVENT_TBL_SIZE > 4
    *ptbl++            = 0x00;
#endif

#if OS_EVENT_TBL_SIZE > 5
    *ptbl++            = 0x00;
#endif

#if OS_EVENT_TBL_SIZE > 6
    *ptbl++            = 0x00;
#endif

#if OS_EVENT_TBL_SIZE > 7
    *ptbl              = 0x00;
#endif
}
#endif

    上面的代码功能比较简单,唯一需要注意的是,Labrosse先生使用条件编译代替了for循环,这样做的目的是减少编译时间(具体的效率,暂不清楚)。

2. INT8U OS_EventTaskRdy (OS_EVENT *pevent, void *msg, INT8U msk)
    当某事件发生时,要将等待该事件任务列表中优先级最高的的任务置于就绪态,信号量、互斥型信号量、消息邮箱、消息队列所对应的POST函数都会调用OS_EventTaskRdy()。这个函数是对内的,即此函数可以被uC/OS II调用,用户应用程序不可以直接调用此函数。源码如下:

#if OS_EVENT_EN > 0
INT8U  OS_EventTaskRdy (OS_EVENT *pevent, void *msg, INT8U msk)
{
    OS_TCB *ptcb;
    INT8U   x;
    INT8U   y;
    INT8U   bitx;
    INT8U   bity;
    INT8U   prio;

    y    = OSUnMapTbl[pevent->OSEventGrp];           
    bity = OSMapTbl[y];
    x    = OSUnMapTbl[pevent->OSEventTbl[y]];
    bitx = OSMapTbl[x];
    prio = (INT8U)((y << 3) + x);                    
    if ((pevent->OSEventTbl[y] &= ~bitx) == 0x00) {  
        pevent->OSEventGrp &= ~bity;                  
    }
    ptcb                 =  OSTCBPrioTbl[prio];      
    ptcb->OSTCBDly       =  0;                       
    ptcb->OSTCBEventPtr  = (OS_EVENT *)0;            
#if ((OS_Q_EN > 0) && (OS_MAX_QS > 0)) || (OS_MBOX_EN > 0)
    ptcb->OSTCBMsg       = msg;                      
#else
    msg                  = msg;                      
#endif
    ptcb->OSTCBStat     &= ~msk;                     
    if (ptcb->OSTCBStat == OS_STAT_RDY) {            
        OSRdyGrp        |=  bity;                    
        OSRdyTbl[y]     |=  bitx;
    }
    return (prio);
}
#endif

    需要注意的是if (ptcb->OSTCBStat == OS_STAT_RDY),这说明最高优先级任务得到该事件后不一定就能进入就绪态,也许该任务由于其他原因“suspend”了。

3. void  OS_EventTaskWait (OS_EVENT *pevent)
    当某任务等待某事件的发生时,信号量、互斥型信号量、消息邮箱、消息队列所对应的PEND函数就会调用OS_EventTaskWait(),是当前任务脱离就绪态,并放到相应的ECB的任务等待表中。这个函数是对内的,即此函数可以被uC/OS II调用,用户应用程序不可以直接调用此函数。源码如下:

#if OS_EVENT_EN > 0
void  OS_EventTaskWait (OS_EVENT *pevent)
{
    OSTCBCur->OSTCBEventPtr = pevent;           
    if ((OSRdyTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0x00) {  
        OSRdyGrp &= ~OSTCBCur->OSTCBBitY;       
    }
    pevent->OSEventTbl[OSTCBCur->OSTCBY] |= OSTCBCur->OSTCBBitX;
    pevent->OSEventGrp                   |= OSTCBCur->OSTCBBitY;
}
#endif

4. void  OS_EventTO (OS_EVENT *pevent)
    这个函数牵涉到任务等待超时问题,uC/OS II中可以为任务等待设置一个等待时间,如果在规定的时间内任务等待的事件得不到相应(没有发生),那么OSTimeTick()函数会因为等待超时而将任务置为就绪态。信号量、互斥型信号量、消息邮箱、消息队列所对应的PEND函数就会调用OS_EventTO()函数,完成上述工作。这个函数是对内的,即此函数可以被uC/OS II调用,用户应用程序不可以直接调用此函数。源码如下:

#if OS_EVENT_EN > 0
void  OS_EventTO (OS_EVENT *pevent)
{
    if ((pevent->OSEventTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0x00) {
        pevent->OSEventGrp &= ~OSTCBCur->OSTCBBitY;
    }
    OSTCBCur->OSTCBStat     = OS_STAT_RDY;      
    OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;    
}
#endif

0 0