(原创文章,欢迎转载,请注明出处)

有朋友问我,为什么有些 RTOS 支持中断嵌套, 有些 RTOS 不支持?

这个问题,我想了一下。先从中断来说吧,中断是什么。当CPU在做一件事情的时候,现在有另外一件事情插进来处理,CPU就中断了当前正在做的事情,执行完插入进来的事情后,继续中断之前的事情。中断这个东西是比较好理解的,就像咱在做家务,有个快递来敲门,听到声音后我去开门,收完快递,继续做家务。。

然而,中断本身不同于RTOS的任务调度,一个光秃秃的CPU,使用前后台系统,它也是支持中断的,不管有没有使用 RTOS 。可见,中断是硬件调度的,与软件关系不大。 既然中断是硬件调度的,那么嵌套中断呢?既然 CPU 已经支持了中断,支持嵌套中断的代价比支持中断的代价高多少呢?假设,CPU 当前正在执行A事务,B、C 两个中断依次到来,且B的优先级低,C的优先级高。

A->B->C->B->A

在A中断进入B时,CPU 需要判断A是否为中断,A 不是中断,CPU 保存A的断点信息,开始执行B;当C中断B时,B是中断,这时发生了中断嵌套。CPU 需要判断 C 的优先级别是否高于 B, 高于B才让中断,不然,随便来个中断, B都要让出CPU控制权,中断频繁点,那B就别执行了。所以,CPU必须判断嵌套中断与被嵌套中断之间的优先级。这时保存了B的断点信息,执行C;C执行完成后,恢复B的断点信息,B恢复执行,执行完成后,又恢复A的断点信息,执行A。

我们来看这个过程,发生中断时,CPU 需要:

  1. 判断是否为嵌套中断,如果是,需要判断中断优先级别;中断优先级别低于被中断的优先级别,则不允许中断;
  2. 如果允许中断,则需要保存断点信息;
  3. 中断服务完成后,恢复断点信息。


其中,2、3两条,只要支持中断是必须要做的工作,对于不支持嵌套中断的CPU来说,第一条可以略去。现在CPU很少能找到不支持中断嵌套的。如果能找到,建议可以做一个展台,把这个东东放进去,做CPU的历史展览吧。:),看来这个代价是很小的。

我们再仔细看看上面这三条,第一条是需要硬件支持的。2、3两条不同的处理器,有不同的做法。我们逐一来看:

ARM7、ARM9 代表的 CPU 是这样做的:
中断分两种,普通中断和快速中断,不同之处就是多了一些分组寄存器,少浪费保护恢复寄存器的时间。中断发生硬件只保存返回地址(lr)和程序状态字(cpsr)。用户需要自己保存被破坏的寄存器的值。中断退出时,用户需要恢复这些寄存器的值,而硬件会自动恢复(lr)、(cpsr)的值。仔细看这个过程,实际上是一个软件和硬件相结合的过程。

Cortex-M3 代表的 CPU 是这样做的:
中断分两种,普通中断和快速中断;但Cortex-M3 有一个中断管理器,发生中断时,硬件会把所有必要的信息全部保存,不需要用户代码操心。中断服务结束时,硬件也会自动恢复这些寄存器,用户也无需参与。这个过程是硬件全部自动完成的,所以cortex-m3中断的代码相对简洁很多。

这两种做法,基本上代表了 cpu 的大部分通行的做法。这里稍微提一下中断的另外一个特性:
Cortex-M3 还支持一个特性,如果有两个A、B中断优先级别相同,A正在执行,B发生中断,当A执行完毕后,立即执行B,并不恢复断点执行一条被中断代码,然后再执行B。这样做最直接的好处,对中断的响应就及时、快速,然而,如果中断过于频繁,直接的结果就是被中断的代码没有执行时间。很多CPU都是返回被中断的代码后,执行一条指令,再次进入中断。这种做法保证了再频繁的中断,被中断的代码都能有时间执行,但来回保存、恢复断点信息,使得CPU浪费大量的执行时间。所以,设计者要充分关注这些细节,才能设计出实时性优良的系统。

这两种做法都需要将信息保存在栈中,然后从栈里恢复信息。这有牵扯到另外一个问题,就是 CPU 要求 ISR 有独立的硬件栈,还是共享 RTOS 任务的栈。

  • ISR 有独立的硬件栈 ,第一次中断时,RTOS 需要使用任务栈保存断点,发生嵌套时,isr 使用独立的硬件栈,而不使用任务的栈。
  • ISR 共享 RTOS 任务的栈 ,这个情况就比较“杯具”了,一股脑的全部使用被中断的任务栈。我们想想,那一个任务栈要多开多大的内存,才能保证最大中断嵌套正常工作?您知道是哪一个任务会被中断 N 次吗?所以,所有的任务栈都必须足够大,以允许最深的嵌套。


从设计的角度来说,中断嵌套要求的设计难度较大,并且这部分全部是与处理器高度相关的,处理器与处理器之间很可能借鉴意义都没有……需要用户自己 Coding……听起来是个不好的消息,好在大部分 rtos 都给出移植的例子,可能有些例子不支持中断嵌套,并不意味着 rtos 真的不支持。

好,到这里我分析的差不多了,总结一下:

1.只有不支持中断嵌套的CPU,没有不支持中断嵌套的 RTOS。
2.如果 RTOS 不支持中断嵌套,请参考以下原因:
  2-1.为了节省宝贵的 RAM;
  2-2.基于实时性的设计要求(系统只有少数几个中断,不频繁,对任务切换的实时性要求高);
  2-3.移植的童鞋可能水平不够或时间不够。

 


最后,如果您知道其他原因,欢迎联系我……

 

(原创文章,欢迎转载,请注明出处)