标题: uC/OS-II学习笔记—事件管理程序 [打印本页]

作者: xueren    时间: 2013-8-1 16:18
标题: uC/OS-II学习笔记—事件管理程序
事件控制块的初始化代码应在操作系统初始化函数OS_Init中被调用,实际上也是如此。

事件控制块的初始化函数是OS_InitEventList,在内核代码os_core.c中。该代码如下所示:

可见,ECB初始化函数OS_InitEventList首先清空了所有的ECB,也就是清空了事件表。然后从0到(OS_MAX_EVENTS-1u)循环对除最后一个ECB之外的所有ECB进行初始化,并顺便构建了单项的链表。循环结束后最后一个ECB的OSEventTbl[OS_MAX_EVENTS-1]的OSEventPtr域指向空地址0,构建完成了空闲事件链表,然后将ECB空闲链表的表头地址给OSEventFreeList,初始化完成。
当建立一个事件或消息(如信号量、邮箱、消息队列)时,如信号量的建立函数OSSemCreate等,需要对事件等代表进行初始化。因为虽然事件等待表在操作系统初始化时调用OS_InitEventList已经被初始化了,但很可能在操作系统的运行过程中被使用过,因此不能保证是被清零的。事件等待表初始化函数实现对指定事件控制块中事件等待表和事件等待组清零,可被操作系统的其他函数调用。
事件等待表初始化函数为OS_EventWaitListInit,代码在内核os_core.c中,参数是ECB的地址,程序如下所示:

可见,事件等代表初始化函数为OS_EventWaitListInit所做的工作就是对指定ECB清空任务等待组和任务等待表。
当任务等待事件发生,并获得ECB后,需要在ECB中标记任务在等待事件的发生,才可以在事件发生时取消任务的阻塞。将任务在ECB中进行登记的函数是OS_EventTaskWait,参数是事件控制块的指针。与OS_EventWaitListInit类似,OS_EventTaskWait在任务调用信号量、邮箱等事件等待函数时被对应的函数调用。因为任务的优先级可以通过当前的TCB指针OSTCBCur得到,因此没有作为参数传递。
设置事件等待的函数OS_EventTaskWait的代码如下所示:

由代码的分析可见,事件等待的函数OS_EventTaskWait只做以下两件事情:
(1)标记。在ECB中登记本任务,即在ECB的事件等待表中对应优先级处标记为1,事件等待组中对应位标记为1.
(2)取消标记。在就绪表和就绪组中取消对该事件的就绪的标记,将就绪表中对应优先级处标记为0,如果就绪表中该任务所在的一组没有任务就绪,将就绪组中的对应位标记为0。
OS_EventTaskRemove是与OS_EventTaskWait相反的操作,当一个事件由于某种原因不再需要等待事件(如任务被删除)时,就需要在该事件的等待表中取消该事件的等待标志,否则会引起严重的后果,例如,去运行一个已经被删除的任务。事件等待组中的一位表示事件等待表中一行8个任务是否有任务在等待事件,因此只是一个任务不再等待不一定要删除事件等待组中的对应标志,需要进行判断。OS_EventTaskRemove的代码如下所示:

由代码可知,OS_EventTaskRemove执行了一项操作,就是取消事件等待表和事件等待组中的任务等待标志。
任务因为等待事件而在ECB中登记自己的等待,当时间发生时,如果该任务是事件等待表中优先级最高的任务,任务呗取消等待而回到就绪态。等待的事件发生的函数为OS_EventTaskRdy,从函数名来看,含义为将等待事件的任务就绪。该函数的声明如下所示:


参数解析如下:
(^_^) prevent:对应的ECB指针
(^_^) pmsg:消息指针。当使用诸如消息队列或消息邮箱的消息服务的时候使用该指针。当是信号量或其他事件的时候不使用该指针。
(^_^) msk:清除状态位的掩码。例如,使用OSSemPost()提交信号量时OS_STAT_SEM,使用OSMboxPost()提交消息的时候使用OS_STAT_MBOX,以清除TCB中的对应状态位。使用该参数的目的是不需要操作系统判定是何种事件发生而增加运行成本。
(^_^) pend_stat:表示等待(pend) 结束,任务就绪的原因,可以是下面的值:
        》》》 OS_STAT_PEND_OK:任务就绪的原因是等待正常结束,诸如事件发生、超时。
        》》》 OS_STAT_PEND_ABORT:因为异常。
返回值:任务优先级。
总结一下,OS_EventTaskRdy的流程如下:
(1) 在事件等待表和事件等待组中找到最高优先级的等待任务的优先级。
(2) 根据优先级查任务优先级指针表,找到该任务的TCB指针。
(3) 对任务控制块的相关参数进行赋值。
(4) 判断任务是否被挂起,如果未被挂起就将任务就绪。完成从阻塞态到就绪态的转换。
(5) 调用OS_EventTaskRemove在ECB的事件等待表中删除该任务。
(6) 返回任务的优先级。






欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1