ARM9中断原理

出处:ARM9 2410移植之ARM中断原理, 中断嵌套的误区,中断号的怎么来的

几天前一个学生问我ARM中断嵌套的问题,我才发现原在我心中理所当然的事对学生来说理解实属不易。
     ARM有七种模式,我们这里只讨论SVC、IRQ和FIQ模式。
     我们可以假设ARM核心有两根中断引脚(实际上是看不见的),一根叫 irq pin, 一根叫fiq pin.
     在ARM的cpsr中,有一个I位和一个F位,分别用来禁止IRQ和FIQ的。
     先不说中断控制器,只说ARM核心。正常情况下,ARM核都只是机械地随着pc的指示去做事情,当CPSR中的I和F位为1的时候,IRQ和FIQ全部处 于禁止状态。无论你在irq pin和fiq pin上面发什么样的中断信号,ARM是不会理你的,你根本不能打断他,因为他耳聋了,眼也瞎了。
     在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以外,根本没有所谓中断嵌套的情况。
   但是再怎么说irq pin 和fiq pin加起来也就2根引脚,那这么多中断源,怎么办呢?不可能谁来了都直接来敲门吧。
    那么接下来该说谁来给irq pin或者 fiq pin发信号呢?上文中可以看到,是老板的客户,也可能是公安。这个事情就是由中断控制器来管理。
    拿最简单的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中的中断号就是根据这个算法把每个中断算一下得来的。
      还有子中断、外部中断,电平触发、边沿触发等,以后再谈。


出处:一起来学嵌入式之ARM9中断机制-中断信号处理过程及实例

最近在学ARM9的裸板编程,中断对设备的控制特别重要,故了解其过程非常重要。

下图可以看到整个中断机制的硬件处理过程。

S3C2440的datasheet里面写着ARM芯片总共有60个中断源,网友也有讨论过不是60个之类的,但是我们以datasheet为准。中断源分内部中断源和外部中断源,I/O的属于外部中断源。

中断能否成功处理,有两部分,1是触发中断信号,2是ARM能否识别中断。

1触发中断信号,很简单,有高电平,低电平,上升沿,下降沿触发四种,至于用那种需要程序员来设置。可是一个设备能否具有触发中断信号的能力,还要看它是否是中断源,这个就要查datasheet了,看看那个引脚接的控制器是否有中断源标志。

2是CPU能否识别中断信号并处理,大家会说,这个简单啊,中断一发过来ARM就会自动处理的啊。实际上,在上面的图可以看出,一个中断信号传到给ARM前,还得经过中断控制器的处理。这个中断处理器的作用是用于集中处理中断信号的筛选和排序的功能。因为60个中断源,在中断控制器里会有对应的控制寄存器控制着,包括状态标志和中断开关。比如说一个二级中断传过来二级中控器,该寄存器相应状态标志的位会变为1,如果这是对应位的开关是0,那么这个中断也就无法往下传了,也就是说信号即使可以触发,但没有传到给ARM处理,那也是没有用的。如果开关是1,那么中断信号也是可以传到下一级的一级中控器的,当然,如果还要往ARM里面传中断信号,这个一级中控器的开关也是要设置为1才行。

综上所述,我们要写一个由中断信号来处理的程序。首先,把我们要控制的设备(前提它属于中断源之一)设置状态为中断信号,第二是把该设备的中断方式(刚才所说的四种之一)设置好。这样我们就完成了设置触发中断信号的工作。接下来就是要让ARM识别我们的中断,也就是要把相应的寄存器来设置好开关即可,这部分我们要查看设备的属于二级中断或外部中断,还是一级中断,然后把相关的开关打开就可以了。

下图是整个中断流程里的寄存器对应表,写代码参考十分有用。

下面给个二级中断设置的思路,我以IRQ中断方式来举例:

比如我们要触发的是INT_TC这个二级中断信号。好,那么我们要打开的开关是什么呢?在二级中断信号里,INTSUBMSK是二级中断信号的开关,我们要在里面找到INT_TC这个位并设置为1即可。二级中断还得传到一级中控器处理,那么我们先找出INT_TC是属于哪个一级中断信号的,看表里的紫色框起来的是二级属于同一个一级信号的,一级信号处理那个也有个紫色框,INT_ADC就是我们要找到的对应一级信号。而它也有对应的开关,那么就是INTMSK这个控制器。我们把INTMSK里的INT_ADC位设置为1就算成功了。

代码也就是  

INTSUBMSK |= ( 0x1 << 9);//因为INT_TC在INTSUBMSK里的第9位,注意从0开始

INTMSK |= (0x1 << 31); //INT_ADC在INTMSK里的第31位。

其他的类似外部中断也是这样操作。只是一级中断的可以直接从一级中控器处理,那么就只设置一级中控器的相应开关即可。也就是说,我们要用到的设备接口,我们就把相应的开关打开就可以了,其他的让ARM来处理就可以了。

这里备注两个问题:

1 为什么要分一级中断和二级中断还有外部中断呢?

答:因为ARM有六十个中断源。一个寄存器有32位,用一个位来标志一个中断源,那肯定不够用。所以我们要用二级中断源还有外部中断源来作为一个二级的解析。我们又会问,为什么二级中断里会有好几个合在一起在一级中控器里?前面说了,不够用,还有一个就是,我们要清楚,在一个中断控制寄存器里,同一时间里只会有一位是为1的,放到IRQ里面,还会有个处理优先级的控制器,会根据优先级来处理哪个中断信号先处理。

2 INTMOD是什么?

答:中断的模式分为FIQ(快速中断)和IRQ(普通中断),前者设置标志寄存器INTMOD的相应位即表示该中断为快速中断,快速中断不用经过优先级的筛选,直接传给ARM处理。而后者就是我们上面的例子说的那种,还需要筛选和处理优先级才能传给优先级。

以上是ARM的中断机制的一些处理方式,但是要写出完整的中断处理代码,我们暂时只是踏出了第一步,请继续看下一篇文章,中断的清除。

出处:一起来学嵌入式之ARM9中断机制-中断清除

上篇文章介绍了一些中断机制里一些信号处理过程,接下来来说说中断的清除。

为什么需要中断清楚呢?因为我们逻辑电路里使用高低电平来描述我们的逻辑1或0的,那我们比如一个按钮作为中断源用下降沿触发,我们按下去,松开得过程,就是高电平降到低电平的过程,产生了下降沿,相应的中断控制寄存器里的位就会记录1。按下去之后,那个高电平中断信号就在寄存器里面记录着,如果我们没有人为地改动,它能改变吗?显然是不能的,那么就需要程序员来人为地消除,否则就会一直发送中断的信号,ARM一直接收和处理这个中断信号显然不是我们想要的。

如何清除,那也是要用到中断信号标志的寄存器如SRCPND,SUBSRCPND等。这里就有个问题,我们是从中断信号的源头开始清除呢还是从靠近ARM的地方开始清除呢?首先看看从靠近ARM的地方开始行不行,我们举例EINT4(这是属于外部中断,下一级是一级中断)的清除。我们的思路是,INTPND设置为0,然后SRCPND(一级中断)相应位设置为0,最后把EINTPEND设置为0对吧?这里就会有问题,INTPND的值是从SRCPND传过来的,那么我们把INTPND清0,但是SRCPND还是没有改变状态,还是为1,那么SRCPND还是会把INTPND设置为1,这样就说明,我们从靠近ARM的那边开始清除是不行的。

好的,我们从源头开始清除,下面是三种中断的处理思路:

一级中断:SRCPND-->INTPND

二级中断:SUBSRCPND-->SRCPND-->INTPND

外部中断:EINTPEND-->SRCPND-->INTPND

我们按顺序把他们清0即可。但是这里要注意!Datasheet里说明,我们把相应位置1即可,它就会自动把它清零,而我们直接赋值置0是无效的。至于为什么要这样?我也不清楚,我猜想是它的内部的逻辑电路可能还有些东西要处理,所以要置1才有效。如果有知道的朋友,请留下评论告诉我一下。

猜你喜欢

转载自blog.csdn.net/wuhenyouyuyouyu/article/details/85278548