1.4.7 中断延迟
什么叫中断延迟
所谓中断延迟,其实在编写裸机程序中经常被用到,我们时常需要靠中断来捕获相关的数据或者事件输入,然后在中断中置起相关标志位,在主函数中的死循环中检查这个标志位,如果置起,说明中断发生了,然后进行相应的处理。与之类似的,freeRTOS的中断延迟是一个道理,中断服务函数不做相关的处理,而是由随后运行的任务来处理,这相比直接在中断服务函数中处理会有一个延迟,好处是不会占用太多的中断时间,使得实时性变差。
这种机制导致的延迟,在相应的处理任务的优先级较高的情况下,几乎与直接在中断中处理的效果是一样的。如下图:
在中断服务函数结束之后,因为处理任务具有更高的优先级而得到立即执行。
大多数的工程师都在试图最小化因为中断导致的执行时间的抖动,因此中断延迟这个机制是很有必要的,因为这个延迟时间是可以确定的(阻塞当前任务的时间加上上下文切换的时间),在如下的情况中断延迟的机制是很有益的:
- 需要执行大量操作
- 需要使用全部峰RTOS API,而不是仅仅中断安全的API
- 需要执行一个不确定的动作,比如在合理的范围内才执行的动作
中断延迟到任务的技术实现
- 集中处理中断延迟
所谓集中处理中断延迟,是使用xTimerPendFunctionCallFromISR()
API将接下来的处理函数作为回调函数提供给RTOS的内核守护任务。通过传递处理函数的指针,在中断服务函数退出后,相应的处理函数会得到执行。从中断退出,到相应的处理函数得到执行,在时间上是连续的,好像这个函数直接由中断调用一样,具体参考xTimerPendFunctionCallFromISR()
的说明文档
集中处理中断延迟的好处是内存占用较小,不需要额外的数据去记录中断源,每个延迟的中断处理函数都由同一个任务来管理。
缺点也是有的:
- 所有的处理函数都执行在RTOS的守护任务的上下文中,这意味着所有的处理函数具有相同的优先级
- 处理函数的指针传递使用定时器的队列,因此RTOS守护任务调用这些函数的顺序是队列的接收顺序,未必是中断的发生顺序
对定时器队列的写和读造成了额外的延迟
应用管理中断延迟
应用管理中断延迟处理执行在每个任务自己的上下文中,因此带来的好处在于:
- 减少额外的中断延迟(因为并不在使用队列传递函数指针)
- 每个中断处理任务可以有不同的优先级,可以使得高优先级的中断具有匹配的高优先级的处理任务
缺点是需要更多的内存,可以参阅“任务通知”部分,当然使用队列和信号量也可以到达相同目的(任务通知占用内存会小些)。