参考:VSF的事件驱动: http://www.jianshu.com/p/f0cbf86d8fed
这里介绍一下VSF的比较关键的设计,就是对各种不同实时性任务的处理,以及一些使用原则和限制。VSF的抢占是事件队列的抢占,运行在PendSV中断里的事件队列和直接抢占运行在main里的事件队列,抢占就只是硬件的中断抢占;VSF的协作是一个事件队列内部的事件,是以协作方式运行的,互相不能抢占。一种特殊情况是没有事件队列的情况,试想各个硬实时中断里,如果没有硬实时操作,而只是发送事件给PendSV事件队列,然后PendSV中再依次处理,是否等效于把这些硬实时中断都改成协作方式(中断互相不能抢占),并且中断处理函数中直接调用事件处理函数?这样可以免去事件队列和相应的代码,并且永远不会存在短时间内产生太多事件而溢出事件队列的情况。
那么什么时候必须用事件队列,什么时候可以省掉事件队列呢?
原则1: 当存在高优先级任务向低优先级任务发送事件的情况,必须使用事件队列,以避免抢占引起的原子性问题。
前面所说的没有事件队列的情况,实际上就是可以不需要硬实时的情况,那就不存在硬实时任务发送事件给软实时任务。那么,什么时候可以不用事件队列也应该很清楚了。实际应用中,一般最高优先级的任务,不存在接收更高优先级任务发送的事件的情况,所以可以不需要事件队列。
上面说的是高优先级任务发事件给低优先级任务,那么低优先级任务发送事件给高优先级任务时候,会出现什么问题呢?
如果高优先级的任务没有事件队列的话,那么低优先级任务发送事件的时候,会调用高优先级任务的事件处理函数(以低优先级执行),这样,就可能存在抢占的问题了。所以,VSF中任务如果调用不同事件队列中的任务的事件处理函数(因为对应的任务没有事件队列),会先关闭对应的事件队列(关闭对应的中断优先级,不会影响中断标志),调用完事件处理函数后,再重新打开。当然,一种最简单的方式是(原则1的扩展):
原则2: 当存在不同优先级任务向本优先级任务发送事件的情况,使用事件队列,以避免抢占引起的原子性问题。
最后要说一下基础模块的线程安全问题,基础模块比如bufmgr、timer等,可能会需要被多种优先级的任务调用,而这些基础模块在设计中,是没有保护的。但是如果在这些模块中,直接关闭中断的话,可能会引起硬实时任务延时过长。这里处理方式可以是这样,这些模块的线程安全问题,是关闭除实时性优先级外,其他优先级(cortexM的BASEPRI寄存器)。限制是,硬实时中,不能使能这些模块。