同级中断可以嵌套吗_这可能是最通俗易懂的⽅式讲解ARM中
断原理以及中断嵌套...
⼏天前⼀个学⽣问我ARM中断嵌套的问题,我才发现原来在我⼼中理所当然的事对学⽣来说理解实属不易。
ARM有七种模式,我们这⾥只讨论SVC、IRQ和FIQ模式。
我们可以假设ARM核⼼有两根中断引脚(实际上是看不见的),⼀根叫 irq pin, ⼀根叫fiq pin。在ARM的cpsr中,有⼀个I位和⼀个F位,分别⽤来禁⽌IRQ和FIQ。
当I位和F位为0时,irq pin上有中断信号过来时,就会打断arm的当前⼯作,并且切换到IRQ模式下,跳到相应的异常向量表(vector)位置去执⾏代码。这个过程是⾃动的,但是返回到被中断打断的地⽅就得您亲⾃动⼿。
当你跳到异常向量表,处于IRQ的模式的时候,此时如果irq pin上⾯⼜来中断信号,此时ARM是不会理你的,irq pin就像秘书,ARM核⼼就像⽼板,⽼板本来在做事,然后来了⼀个客户,秘书打断它,让客户进去。⽽此时再来⼀个客户,要么秘书不断去敲门问,要么客户⾛⼈。⽼板第⼀个客户没有会见完,不会理你。
但是有⼀种情况例外,当ARM处在IRQ模式,这个时候fiq pin来了⼀个中断信号,fiq pin是什么?快速中断,好⽐公安局的来查刑事案件,才不管⽼板是不是在会见客户,直接打断,进⼊到fiq模式,跳到相应的fiq的异常向量表处去执⾏代码。那如果当ARM处理FIQ模
式,fiq pin⼜来中断信号,也就是⼜⼀批公安来了,那没戏,都是执法⼈员,你打不断我。如果此时irq pin来了呢?来了也不理,正在办案,还敢来妨碍公务。
所以得出⼀个结论: IRQ模式只能被FIQ模式打断,FIQ模式下谁也打不断。
在打不断的情况下,irq pin 或fiq pin随便你怎么发中断信号,都是⽩发。
所以除了fiq能打断irq以外,根本没有所谓中断嵌套的情况。
x86架构和arm架构区别
但是再怎么说irq pin 和fiq pin加起来也就2根引脚,这么多中断源,怎么办呢?不可能谁来了都直接敲门吧。
接下来该说谁来给irq pin或者 fiq pin发信号。从上⽂可以看到,可能是⽼板客户,也可能是公安。在ARM中,这个事情由中断控制器管理。
拿最简单的2410/2440的中断控制器举例,中断控制器加⼀个⼦中断控制器,还有⼀个外部中断控制器管理了50多个中断资源,说穿了有50多个脚。这些脚除了外部中断都是规定了功能的,⽐如WDT、LCD、DMA等,这个功能不能改,因为2410/2440内部硬件连线已经决定了。
当WDT和DMA中断都到来时,会被送到SRCPND寄存器中,两个中断都在⾥⾯,到底把哪⼀个送给ARM呢?这个时候先看INTMOD,也就是中断模式寄存器:哪个中断被设置成快速中断,哪个就被送上去;如果两个都被设置为快速中断呢?这不可能,因为同⼀时间只能有⼀个中断可以被设成快速中断。所以,如果有快速中断,这个时候直接给fiq pin发中断信号,打断ARM。
要是没有快速中断呢,这个时候就看INTMSK,看WDT和DMA有没有被屏蔽,如果DMA在INTMSK被屏蔽,只有WDT继续向上送,如果都没有屏蔽,那么他们两个同时进⼊优先级寄存器PRIORITY,在这⾥根据优先级设置,⼀定会分出⼀个⾼⼀个低的优先级出来,优先级⾼的那个被送到INTPND寄存器,所以INTPND随时随地有且只有⼀个中断在⾥⾯。只要INTPND⾥⾯有中断,irq pin就不会⼀直不
断给ARM 发中断信号,当第⼀次发的时候,中断了ARM,这个时候ARM进⼊相应的异常向量并处于IRQ模式。
此时,INTPND仍然不断的通过irq pin向ARM发中断信号,但是此时ARM已经处于IRQ模式,不会理睬你。当你中断处理完,要退出IRQ 模式,这个时候要⼩⼼,如果退出IRQ模式之前不清除INTPND⾥⾯的中断位,刚退出IRQ模式,⼜会被中断,因为INTPND⼀直在发中断信号。所以在退出IRQ模式前⼀定要清除INTPND⾥⾯的中断位。
光清除INTPND⾥⾯的位还不⾏,因为SRCPND⾥⾯WDT和DMA的中断在,当你刚清除完INTPND,结果SRCPND⾥⾯⼜选了⼀个中断出来送到INTPND⾥⾯。所以正确的处理⽅法是退出IRQ模式之前,先清除SRCPND⾥相应的中断位,再清除INTPND⾥相应的位。请注
意,SRCPND⾥⾯可能有多个位,所以清除你已处理过的中断就⾏,⽽INTPND⾥⾯只可能有⼀位,直接清掉即可。
再说说Linux的情况。Linux不⽤FIQ,只⽤到了IRQ。但是我们有时候⼀个中断需要处理很长时间,我们需要占⽤IRQ模式那么长的时间吗?不需要,linux在IRQ模式下只是简单的记录是什么中断,马上切换回SVC模式,换句话说,linux的中断处理都是在SVC模式下处理的。
那么中断号是怎么来的呢?它在ARM上固定死了,相应的中断号只有⼀个办法得到:查询irqs.h 。先⽤⼀个中断号注册⼀个中断处理程序,当中断发⽣的时候,Linux怎么知道是我这个中断号发⽣的中断呢?在处理中断的时候,先读取INTPND,根据需要再读取EINTPEND 或SUBSRCPND计算出⼀个中断号,相应的处理算法在get_irq_nr_base这个宏中。irqs.h中的中断号就是根据这个算法把每个中断号算出来的。
「基础知识普及」ARM与X86 CPU架构区别
ARM指令adr adrl ldr mov简单科普
了解更多