谈谈ARM中断嵌套
1 何为中断嵌套
中断嵌套就是指高优先级的事件可以打断低优先级的事件(反过来不可以),而处理完高优先级事件后还得回来继续处理低优先级事件。
打个比方,你在看电视(一般任务),你妈叫你洗2只碗(中断来了),你刚洗完一只,你爸叫你去打水(中断也被中断了,还让不让人活啊),由于你爸更有威信(优先级更高),所以你必须得先去打水,等你打完水,还得回来继续洗碗,洗完碗才能继续看电视。这个过程就是带中断嵌套的中断。
还有一种使用错误的中断嵌套,就是高优先级事件可以被低优先级事件打断,这是个比较严重的问题,虽然也是嵌套了,但完全偏离的中断嵌套的初衷,后面会分析这种情况。
下文提到的中断嵌套都指的是高优先级事件打断低优先级事件的中断嵌套。
2 为什么需要中断嵌套
对最紧急的事件进行相应是实时系统的关键,紧急事件有很多,但总有轻重,如果最紧急的事件得不到处理,就可能酿成灾难。
3 处理器是否支持中断嵌套
你可能会问,我的处理器能支持中断嵌套吗,这个还要具体情况具体分析。一款处理器能否支持中断嵌套,最重要的是看它是否具有保存中断现场的能力,这个包括两方面,一是保存处理器的寄存器文件,二是保存中断控制器的硬件环境。保存处理器的寄存器文件很简单,直接压栈就可以了,而保存中断控制器的硬件环境就不一定能实现了,这要求中断控制器具有硬件栈(因为软件是无法访问中断控制器的内部环境的)。
下面就具体进行分析,分析对象:
STM32F(CORTEX-M3)
NXP的LPC系列(ARM7)
ST的STR7(ARM7)
先透露一下结论,支持中断嵌套的只有STM32F和STR7。
3.1 LPC系列
先谈谈ARM7TDMI(以下简称ARM7)。ARM7本身没有集成中断控制器,而是由芯片厂商自己实现,市场上出现了形形色色的基于ARM7的微控制器。
ARM7大部分中断都在IRQ下处理,而进入IRQ后是无法再被中断的(就好像你妈叫你洗碗的时候,你带着耳机听歌,所以听不到你爸的命令)。但是我还是想实现中断嵌套,怎么办呢?于是程序员开动脑筋,想出了办法:退出IRQ,在SYS模式下执行中断代码(很多情况下确实是这么做的)。这样又产生了新的问题:优先级问题怎么解决?继续努力:退出IRQ的时候禁止比当前优先级低的中断源产生IRQ中断,执行完代码的时候使能。但这要求中断控制器具有挂起未响应中断(而且已被禁止)的能力。
脑子有点乱,下面用表格3.1来表示解决问题的过程。
步骤 |
问题 |
解决方法 |
1 |
IRQ模式无法被新的IRQ中断 |
切换到SYS模式去执行中断代码 |
2 |
SYS模式会被低优先级的IRQ中断源打断 |
关闭低优先级IRQ中断源 |
3 |
被禁止的低优先级IRQ中断需要被挂起 |
取决于中断控制器的实现方式 |
表格3.1 ARM7解决中断嵌套问题的过程
以LPC2368为例(为什么用LPC2368?很简单,因为作者用过,而且可以代表这个系列),表格3.1中的步骤1、2都实现了,但是步骤3没实现,因为该中断控制器无法保存被禁止且被挂起的中断。作者读过一些在该微处理器上实现中断嵌套的代码,基本上是只实现了步骤1,因此实际上一种错误的中断嵌套。
3.2 STR7
STR7(ARM7TDMI)的中断控制器同样是厂商实现的,但是本身就实现了中断状态的硬件压栈(CPU工作寄存器的保存还是需要软件控制),所以中断嵌套是可以实现的。
3.3 STM32F
STM32F1和STM32F2系列用的是CORTEX-M3CPU,CORTEX-M3本身集成了NVIC(可嵌套的向量中断控制器),可以说是一个非常先进的中断控制器,甚至连CPU工作寄存器都会自动压栈,建议读一下《CORTEX-M3权威指南》这本书。总之,CORTEX-M3的中断控制器基本把保存现场的工作都做了,程序员终于解放了,中断嵌套也得到了完美实现。
4 名词解释
4.1 VIC与NVIC
VIC是向量中断控制器,主要意思是每一个中断线连接到一个中断函数的地址,有点像数学中的向量(或者说是数组)。
NVIC则是在VIC的基础上实现了中断嵌套。