UCOS之事件控制块

事件控制块中的具体使用过程:(以信号量为例)

        1。与任务控制块的管理类似,UCOS在系统初始化的时候会在OSIint() 函数中控制应用程序使用的事件总数创建一个空的事件控制块链表,并用OSEventPtr作用指针指向他。以后每当创建一个事件时,就会从该空链表中取一个事件控制块。

         2。创建一个信号量:在使用信号量前,程序必须调用函数OSSEMCreat()来创建一个信号量。我们一般在一个任务中创建一个信号量。调用OSSEMCreat()时,会从空事件控制块中取得一个事件控制块。在成功申请后,先对该事件控制块进行初始化,即把其类型设为信号量,并置信号量初值,事件指针设为空指针,然后调用OSEventWaitListInit()函数对事件控制任务控制块的等待任务列表进行初始化:即将OSEventGrp和OSEventTbl[]全部清零置空。最后,OSSemCreate()返回给调用函数一个指向该任务控制块的指针。

     3。等待一个信号量:创建完一个信号量后,使用该信号量就通过OSSemPend()函数来请求信号量

(1)首先检查指针pevent所指的任务控制块是否是由OSSemCreate()建立的。如果信号量当前是可用的(信号量的计数值大于0),将信号量的计数值减1,然后函数将“无错”错误代码返回给它的调用函数。显然,如果正在等待信号量,这时的输出正是我们所希望的,也是运行OSSemPend()函数最快的路径。

(2)如果此时信号量无效(计数器的值是0),OSSemPend()函数要进一步检查它的调 用函数是不是中断服务子程序。在正常情况下,中断服务子程序是不会调用OSSemPend()函数的。这里加入这些代码,只是为了以防万一。当然,在信号 量有效的情况下,即使是中断服务子程序调用的OSSemPend(),函数也会成功返回,不会出任何错误。

(3)如果信号量的计数值为0,而OSSemPend()函数又不是由中断服务子程序调用的,则调用OSSemPend()函数的任务要进入睡眠状态,等待另一个任务(或者中断服务子程序)发出该信号量 。OSSemPend()通过将任务控制块中的状态标志.OSTCBStat置1,把任务置于睡眠状态(操作在OSEventTaskWait()函数中执行),等 待时间也同时置入任务控制块中。该值在OSTimeTick()函数中被逐次递减。因为当前任务已经不是就绪态了,所以任务调度函数将下一个最高优先级的 任务调入,准备运行。当信号量有效或者等待时间到后,调用OSSemPend()函数的任务将再一次成为最高优先级任务。

简单说就是这些情况下,要把该任务登记在事件控制块的等待任务列表中,并把任务控制块的任务状态置为等待状态和把任务置为非就绪任务,直到超时到或信号量来。

     可以进行超时设置,在时间到的时候结束等待状态而直接进入就绪状态。也可以使用无等待函数OSSemAccept()来请求信号量,即当一个任务请求一个信号量时,如果该信号量暂时无效,则让该任务简单地返回,而不是进入睡眠等待状态    

     4。发送一个信号量:OSSemPost()。

     (1)首先检查参数指针pevent指向的任务控制块是否是OSSemCreate()函数建立的

     (2)接着检查是否有任务在等待该信号量。如果该事件控制块中的.OSEventGrp域不是0,说明有任务正在等待该信号量。这时,就要调用函数OSEventTaskRdy,使一个任务进入就绪状态。把其中的最高优先级任务从等待任务列表中删除,并使它进入就绪状态

     (3)然后,调用OSSched()任务调度函数检查该任务是否是系统中的最高优先级的就绪任务。如果是,这时就要进行任务切换[当OSSemPost()函数是在任务中调用的],准备执行该就绪任务。如果不是,OSSched()直接返回,调用OSSemPost()的任务得以继续执行。如果这时没有任务在等待该信号量,该信号量的计数值就简单地加1。

posted @ 2013-03-08 23:11  顶顶顶顶  阅读(603)  评论(0)    收藏  举报