通过 uCOS_II.H 中定义的 OS_EVENT 数据结构来维护一个事件控制块的所有信息 ,也就是控制块 ECB。
- OSEventType 定 义 了 事 件 的 具 体 类 型 。 它 可 以 是 信 号 量 ( OS_EVENT_SEM ) 、 邮 箱 (OS_EVENT_TYPE_MBOX)或消息队列(OS_EVENT_TYPE_Q)中的一种。用户要根据该域的具体值来调用相应的系统函数,以保证对其进行的操作的正确性。
- OSEventPtr 指针,只有在所定义的事件是邮箱或者消息队列时才使用。 当所定义的事件是 邮箱时,它指向一个消息,而当所定义的事件是消息队列时,它指向一个数据结构
- OSEventCnt 当事件是一个信号量时,.OSEventCnt 是用于信号量的计数器
- OSEventTbl[] 和 .OSEventGrp
- 每个等待事件发生的任务都被加入到该事件事件控制块中的等待任务列表中,该列表包 括.OSEventGrp 和.OSEventTbl[]两个域
- 所有的任务的优先级被分成 8 组(每组 8 个优先级),分别对应.OSEventGrp 中的 8 位。当 某组中有任务处于等待该事件的状态时,.OSEventGrp 中对应的位就被置位。相应地,该任务在.OSEventTbl[]中的对应位也被置位
- .OSEventTbl[]数组的大小由系统中任务的最低优先级 决定,这个值由 uCOS_II.H 中的 OS_LOWEST_PRIO 常数定义,在任务优先级比较少的情况 下,减少 µC/OS-II 对系统 RAM 的占用量。
事件控制块的操作
在 µC/OS-II 中,事件控制块的总数由用户所需要的信号量、邮箱和消息队列的总数决定。 该值由 OS_CFG.H 中的#define OS_MAX_EVENTS 定义。在调用 OSInit()时,所有事件控制块被链接成一个单向链表——空闲事件控制块链表。每当建立一个信号量、邮箱或者消息队列时,就从该链表中取出一个空闲事件控制块,并对它进行初始化。因为信号量、邮箱和消息队列一旦建立就不能删除,所以事件控制块也不能放回到空闲事件控制块链表中。
初始化一个事件控制块,OSEventWaitListInit()
当建立一个信号量、邮箱或者 消息队列时,相应的建立函数 OSSemInit(),OSMboxCreate(),或者 OSQCreate()通过调用 OSEventWaitListInit()对事件控制块中的等待任务列表进行初始化。该函数初始化一个空的等 待任务列表,其中没有任何任务。该函数的调用参数只有一个,就是指向需要初始化的事件控制块的指针pevent。
使一个任务进入就绪态,OSEventTaskRdy()
当发生了某个事件,该事件等待任务 列表中的最高优先级任务(Highest Priority Task – HPT)要置于就绪态时,该事件对应的 OSSemPost(),OSMboxPost(),OSQPost(),和 OSQPostFront()函数调用 OSEventTaskRdy()实现该操作。
使一个任务进入等待某事件发生状态, OSEventTaskWait()
当某个任务要等待一个事件的发生 时,相应事件的 OSSemPend(),OSMboxPend()或者 OSQPend()函数会调用该函数将当前任务从就 绪任务表中删除,并放到相应事件的事件控制块的等待任务表中。
由于等待超时而将任务置为就绪态, OSEventTO()
当在预先指定的时间内任务等待的事件没 有发生时,OSTimeTick()函数会因为等待超时而将任务的状态置为就绪。在这种情况下,事件的 OSSemPend(),OSMboxPend()或者 OSQPend()函数会调用 OSEventTO()来完成这项工作。
uCOS-II V2.9.11中对事件操作函数更多,但也基本类似,重在领会精髓,如下图: