ucosiii对从中断发布消息或信号有两种模式:直接发布和延迟发布。
直接发布
指的是直接在中断函数里发布消息OSTaskSemPost()等函数,举例,节拍中断函数里调用时钟节拍函数 ,里面会给系统的时钟节拍任务OS_TickTask()发布消息,叫它进行时钟节拍列表的更新(关于这里具体知识,可以看我这篇文章,ucosiii实时嵌入式操作系统时间片实现原理深入解析),这样就还是在中断函数里调用的消息发布函数,如下图所示。
延迟发布
中断函数仅仅把消息放入一个缓冲队列中,同时把中断服务管理任务 OS_IntQTask()(这个系统任务的优先级是最高的0)加入任务就绪表,任务调度,退出中断了。然后发消息OSTaskSemPost()函数是在中断服务管理任务 OS_IntQTask()里被调用完成的。相当于中断耗时操作任务化。其中是需要打开一个宏OS_CFG_ISR_POST_DEFERRED_EN的。
这样做的好处是:因为OSTaskSemPost()是系统公共资源(把对应任务的消息等待标志置位,再放入任务就绪表,以及队列的一些处理,属于比较耗时的),别的任务或者中断函数都可以访问它,所以在调用它的时候,得对其进行临界资源保护,要么使用开关中断的方式,要么使用调度器加锁的方式。
第一种直接发布的方式直接在中断函数里调用它,如果采用调度器加锁,虽然其他任务不能访问它了,但是其他更高优先级中断发生了还是可以抢占访问它,所以只能采用开关中断的方式保护它,由于这个OSTaskSemPost()函数比较耗时,所以,这段时间内外部中断,其他任务都得不到响应,即影响了系统实时性。
第二种延迟发布的方式,如果把OSTaskSemPost()放到系统中断服务管理任务 OS_IntQTask()里调用,如果还是采用开关中断的方式保护它,那么跟第一种直接发布方式响应一样了,都是要开关中断这么长时间。但是如果这时在中断服务管理任务 OS_IntQTask()里采用调度器加锁的方式,其他任务就访问不了了,但是中断函数呢,也是不行的,因为第二种延迟发布方式就是要打开一个宏OS_CFG_ISR_POST_DEFERRED_EN的,而这个宏就是可以限制所有中断函数对OSTaskSemPost()等消息资源的访问,从而所有中断函数也访问不了,这样就实现了对它的保护。总结前面说的和从上图我们可以看出,第二种延迟发布方式的开关中断时间就是把消息放入缓冲队列而已(这个时间是非常短的),这样就减少了关中断的时间,从而提高了外部需要快速响应的中断的响应速度。但是因为另外加入了一个系统中断服务管理任务 OS_IntQTask(),且还有调度器加锁解锁的过程,从而使得其他任务的延迟时间变大了。