UC/OS II事件管理(1)

ucosii支持事件,事件包括信号量、消息等机制。需要配置OS_EVENT_EN、OS_MAX_EVENTS等相关的宏。
事件控制块(ECB)
事件控制块(ECB)是事件管理的核心数据结构。其定义如下:
typedef struct os_event {
    INT8U    OSEventType;                    //事件类型,具体有信号量、消息邮箱、消息队列、互斥信号量、事件标志组,都相关的宏
    void    *OSEventPtr;                      //指向下一个ECB或者是消息或是队列的指针   
    INT16U   OSEventCnt;                     //信号量的计数值,就只跟信号量有关系,跟其他事件没有关系
    OS_PRIO  OSEventGrp;                     //等待事件标志表
    OS_PRIO  OSEventTbl[OS_EVENT_TBL_SIZE];  //等待事件标志组

#if OS_EVENT_NAME_EN > 0u
    INT8U   *OSEventName; //事件名称
#endif
} OS_EVENT;
#endif
等待事件表和等待事件标志组跟就绪表和就绪组基本上一样。

事件控制块在ucosii中以数组的方式定义OS_EVENT     OSEventTbl[OS_MAX_EVENTS];
OS_MAX_EVENTS可以根据需要自己配置,系统默认值是10。

空闲的时间控制块都组成一个单链表,并且由指针OSEventFreeList指向该链表。

事件控制块初始化函数OS_InitEventList
该函数在系统开始前做在调用OSInit()进行初始化的时候需要用到该函数。
该函数主要功能的将ucosii中定义的事件控制块形成链表,并且对各个时间控制块的成员进行相应的初始化。

等待事件设置函数OS_EventTaskWait
这个函数是将对应的事件控制块以及相应的事件进行设置。这个函数是将对应的事件控制块以及相应的事件和申请任务进行设置。将当前的任务在对应ECB中登记,更新任务的运行状态。
void  OS_EventTaskWait (OS_EVENT *pevent)  //os_core.c中定义
{
    INT8U  y;
    OSTCBCur->OSTCBEventPtr               = pevent;                 //将任务控制块的事件控制块指针指向该事件控制块
    pevent->OSEventTbl[OSTCBCur->OSTCBY] |= OSTCBCur->OSTCBBitX;    //更新表和数组
    pevent->OSEventGrp                   |= OSTCBCur->OSTCBBitY;

    y             =  OSTCBCur->OSTCBY;            
    OSRdyTbl[y]  &= (OS_PRIO)~OSTCBCur->OSTCBBitX;
    if (OSRdyTbl[y] == 0u) {                      /* Clear event grp bit if this was only task pending */
        OSRdyGrp &= (OS_PRIO)~OSTCBCur->OSTCBBitY;
    }
}
取消等待事件(OS_EventTaskRemove)就是将该上面函数的逆。


等待事件中的任务就绪OS_EventTaskRdy
当有事件发生的时候,就有必要更新事件控制块,同时将在ECB事件表和就绪组进行更新,并将注册的任务(此时应该已经是阻塞了)的状态进行更新
INT8U  OS_EventTaskRdy (OS_EVENT  *pevent,  void      *pmsg, INT8U      msk,INT8U      pend_stat)
该函数的参数解释:OS_EVENT  *pevent 对应的事件控制块  void      *pmsg 消息指针,只有在用到消息的时候才会用到
 INT8U      msk     清除状态的掩码。前面我们知道,TCB中的OSTCBStat中不同位关于不同事件的标志位,该掩码就是用来消除因等待该事件而OSTCBStat相应的位。
NT8U      pend_stat 表示等待(阻塞)任务等待结束,任务就绪的原因。可能是这几个值

#define  OS_STAT_PEND_OK                0u  //正常结束,是事件发生
#define  OS_STAT_PEND_TO                1u  //等待超时
#define  OS_STAT_PEND_ABORT             2u  //异常      

其代码主要如下:
找到最高优先级的注册任务
    y    = OSUnMapTbl[pevent->OSEventGrp];             
    x    = OSUnMapTbl[pevent->OSEventTbl[y]];
    prio = (INT8U)((y << 3u) + x);                     

ptcb                  =  OSTCBPrioTbl[prio];        //指向任务等待优先级最高的任务控制块
    ptcb->OSTCBDly        =  0u;                        //将其等待事件清零(因为在等待的时间里,时间发生了)
#if ((OS_Q_EN > 0u) && (OS_MAX_QS > 0u)) || (OS_MBOX_EN > 0u)
    ptcb->OSTCBMsg        =  pmsg;                      //发送消息
#else
    pmsg                  =  pmsg;                      /* Prevent compiler warning if not used        */
#endif
    ptcb->OSTCBStat      &= (INT8U)~msk;                //更新任务控制块的状态
    ptcb->OSTCBStatPend   =  pend_stat;                 //跟新相应任务控制块的阻塞状态
                                                        /* See if task is ready (could be susp'd)      */
    if ((ptcb->OSTCBStat &   OS_STAT_SUSPEND) == OS_STAT_RDY) {
        OSRdyGrp         |=  ptcb->OSTCBBitY;           //更新就绪数组和就绪表
        OSRdyTbl[y]      |=  ptcb->OSTCBBitX;
    }

    OS_EventTaskRemove(ptcb, pevent);                   //将该任务从该等待事件中取消
#if (OS_EVENT_MULTI_EN > 0u)
    if (ptcb->OSTCBEventMultiPtr != (OS_EVENT **)0) {   //若是多事件等待,相关的操作,这个在后面再介绍
        OS_EventTaskRemoveMulti(ptcb, ptcb->OSTCBEventMultiPtr);
        ptcb->OSTCBEventPtr       = (OS_EVENT  *)pevent;
    }
#endif

    return (prio); //返回就绪状态的优先级
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值