异常响应的基本原则就是只要中断挂起寄存器为 0,而且该中断没有被屏蔽,就可进入中断挂起状态。如果在进入handler模式之前,挂起寄存器被清除掉,则进入中断服务程序。
如果挂起寄存器被清 0(不管是软件清除,还是通过进入中断服务程序方式清除),就可响应新的异常触发信号。如果挂起寄存器已经为 1,对于外部新的中断请求,也仅响应一次。
异常响应的状态主要有以下 6 种。
(1)当中断输入脚生效后,该中断就被挂起。即使后来中断源取消了中断请求,已经被标记成挂起的中断也被记录下来。当在系统中它的优先级最高时,它就会得到响应,如图1-11 所示。
图 1-11 中断响应
(2)如果在某个中断得到响应之前,其挂起状态被清除了(例如,当PRIMASK或FAULTMASK置位时,软件清除了挂起状态标志),则中断被取消,如图 1-12 所示。
图 1-12 挂起状态被提前清除掉
(3)当某中断的服务例程开始执行时,就称此中断进入了“活跃”状态,并且其挂起位会被硬件自动清除。在一个中断活跃后,直到其服务例程执行完毕,并且返回后,才能对该中断的新请求予以响应。当然,新请求的响应也是由硬件自动清零并挂起标志位的。中断服务例程也可以在执行过程中把自己对应的中断重新挂起(使用时要注意避免进入“死循环”),如图 1-13 所示。
图 1-13 中断请求被清除
(4)如果中断源上一直存在请求信号,该中断就会在其上次服务例程返回后再次被置为挂起状态,在这一点上,CM3 和传统的ARM7TDMI是相同的。这种情况发生在电平触发源类型的中断过程中,如图 1-14 所示。
图 1-14 请求一直有效
(5)如果某个中断在得到响应之前,其请求信号以若干脉冲形式呈现,则被视为只有一次中断请求,多出的请求脉冲全部丢失,这种情况是由于中断请求过快造成的。
假如设计程序时,将外部中断EINT0 的优先级设定得比较低,虽然触发多次中断,但因为其他高优先级的中断一直占用CPU,所以最后将仅表现为响应一次中断。因此,对中断的优先级及中断响应时长都需要严格规划好,否则会出现各种意想不到的问题,如图 1-15 所示。
图 1-15 中断请求多次触发
(6)如果在服务例程执行过程中,中断请求释放了,但是在服务例程返回前又重新被置为有效,则CM3 会记住此动作,重新挂起该中断。例如,使用SysTick时,如果中断处理程序比较长(运行时间需要 1ms),但时钟间隔设置比较短(设置成了 500μs),这种情况发生后,程序将一直占用处理器,除非具有更高优先级的中断产生,如图 1-16 所示。
从最后两种形式可以看出,中断的挂起状态影响着中断的响应次数。因为中断挂起状态只能是 0 和 1,无其他状态,所以只要该状态寄存器被清除,就可以响应下一次中断了。该寄存器如果已经为 1,则将无法响应新的状态。
图 1-16 中断挂起状态消失后重新触发