在CM3中,中断服务例程可以纯用C来写。与ARM7的情况相比,后者往往需要首尾都加以汇编封皮,以保证所有寄存器都保护了。另外,在中断嵌套时,处理器需要切换到另外的模式,以防止信息丢失。这些跨系统实时性和带来入门难度的繁文缛节在CM3中都被消灭了,使得编程时舒心很多。
如果用汇编来写ISR,其骨架看上去差不多如下所示:
irql_handler
;处理中断请求
ミ
;消除在设备中的IRQ请求信号
ミ
;中断返回
BX LR
如果ISR逻辑比较复杂,则常常需要更多的寄存器,这时就要启用R4-R11了。但是它们不是CM3自动入栈的,使用前必须手工PUSH。下一个例子演示了一个保险的笨方法,保护了所有的寄存器,其实难副如果内存够用,使用笨方法作为起点也不失为一个不错的主意,等到日后优化程序时再去掉没有使用的寄存器。
irql_handler
PUSH {R4-R11,LR}
;处理中断请求 ;保存所有可能用到的,又没有被自动入栈的
ミ
;消除在设备中的IRQ请求信号
ミ
;中断返回
P0P {R4-R11,PC}
因为POP也是启动中断返回的一条途径,所以我们把寄存器的出栈与中断返回合并在一条POP中,使程序更精练。
有些外设的中断请求信号需要ISR手工清除,如:外设的中断请求是持续的电平信号——显然,对于稍纵即逝的脉冲型的请求,是无需手工清除的。若电平型中断请求没有清除,则中断返回后将再次触发已经服务过的中断,以前在AMR7中,外设必须使用这种“电平保持”的方式,直到中断被响应,因为那个时候的中断控制器没有保存挂起状态。CM3解决了这个问题:只要检测到曾经出现的中断请求,NVIC就会记住它,硬件只需给一个脉冲,无需一直保持请求电平,持续的电平反而成为一种讨厌的事了,而且当其服务例程执行时,NVIC自动挂起状态清除,对于这种情况,就不必在ISR中软件清除请求信号了。 |