使用中断的步骤:1、当发生中断IRQ时,CPU进入“中断模式”,这时使用“中断模式”下的堆栈;当发生快中断FIQ时,CPU进入“快中断模式”,这时使用“快中断模式”下的堆栈。所以在使用中断前,先设置好相应模式下的堆栈。2、对于“Requestsources(withoutsub-register)”中的中断,将INTSUBMSK寄存器中相应位设为03、将INTMSK寄存器中相应位设为04、确定使用此的方式:是FIQ还是IRQ。a.如果是FIQ,则在INTMOD寄存器设置相应位为1b.如果是IRQ,则在RIORITY寄存器中设置优先级使用中断的步骤:5、准备好中断处理函数,a.中断向量:在中断向量设置好当FIQ或IRQ被触发时的跳转函数,IRQ、FIQ的中断向量地址分别为0x00000018、0x0000001cb.对于IRQ,在跳转函数中读取INTPND寄存器或INTOFFSET寄存器的值来确定中断源,然后调用具体的处理函数c.对于FIQ,因为只有一个中断可以设为FIQ,无须判断中断源d.中断处理函数进入和返回6、设置CPSR寄存器中的F-bit(对于FIQ)或I-bit(对于IRQ)为0,开中断s3c2410中断异常处理在进入正题之前,我想先把ARM920T的异常向量表(ExceptionVectors)做一个简短的介绍。:]ARM920T的异常向量表有两种存放方式,一种是低端存放(从0x00000000处开始存放),另一种是高端存放(从0xfff000000处开始存放)。关于为什么要分两种方式进行存放这点我将在介绍MMU的文章中进行说明,本文采用低端模式。ARM920T能处理有8个异常,他们分别是:Reset,Undefinedinstruction,SoftwareInterrupt,Abort(prefetch),Abort(data),Reserved,IRQ,FIQ下面是某个采用低端模式的系统源码片段:/*****************************************************************************_start:bHandle_ResetbHandleUndefbHandleSWIbHandlePrefetchAbortbHandleDataAbortbHandleNotUsedbHandleIRQbHandleFIQ…..…..othercodes…...*****************************************************************************/上面这部分片段一般出现在一个名叫“head.s”的汇编文件的里,“bHandle_Reset”这条语句就是系统上电之后运行的第一条语句。也就是说这部分代码的二进制码必须位于内存的最开始部分(这正是低端存放模式),因为上电后CPU会从SDRAM的0x00000000处取第一条指令并执行。AddressInstruct0x00000000:b Handle_Reset0x00000004:bHandleUndef0x00000008:bHandleSWI0x0000000C:bHandlePrefetchAbort0x00000010:bHandleDataAbort0x00000014:bHandleNotUsed0x00000018:bHandleIRQ0x0000001C:bHandleFIQ上面是该程序段在系统上电后加载到内存后的分布情况,我们可以看到每条指令占用了4个字节。上电后,PC指针会跳转到Handle_Reset处开始运行。以后系统每当有异常出现,则CPU会根据异常号,从内存的0x00000000处开始查表做相应的处理,比如系统触发了一个IRQ异常,IRQ为第6号异常,则CPU将把PC指向0x00000018地址(4*6=24=0x00000018)处运行,该地址的指令是跳转到“中断异常服务例程”(HandleIRQ)处运行。以上就是我对异常向量表的一个简单介绍。现在可以进入我们文章的主题“中断异常处理”,s3c2410的中断分快中断(FIQ)和普通中断(IRQ),我们讨论的重点是普通中断(IRQ)。s3c2410的中断异常处理模块总共由以下寄存器构成SRCPND(SOURCEPENDINGREGISTER)INTMOD(INTERRUPTMODEREGISTER)INTMSK(INTERRUPTMASKREGISTER)PRIORITY(PRIORITYREGISTER)INTPND(INTERRUPTPENDINGREGISTER)INTOFFSET(INTERRUPTOFFSETREGISTER)SUBSRCPND(INTERRUPTSUBSOURCEPENDING)INTSUBMSK(INTERRUPTSUBMASKREGISTER)下面我将讲解每个寄存器在一个中断处理流程中所扮演的角色SRCPND/SUBSRCPND这两个寄存器在功能上是相同的,它们是中断源引脚寄存器,在一个中断异常处理流程中,中断信号传进中断异常处理模块后首先遇到的就是SRCPND/SUBSRCPND,这两个寄存器的作用是用于标示出哪个中断请求被触发。SRCPND的有效位为32,SUBSRCPND的有效位为11,它们中的每一位分别代表一个中断源。SRCPND为主中断源引脚寄存器,SUBSRCPND为副中断源引脚寄存器。这里列举出SRCPND的各个位信息:每个位的初始值皆为0。假设现在系统触发了TIMER0中断,则第10bit将被置1,代表TIMER0中断被触发,该中断请求即将被处理(若该中断没有被屏蔽的话)。SUBSRCPND情况与SRCPND相同,这里就不多讲了。INTMOD寄存器有效位为32位,每一位与SRCPND中各位相对应,它的作用是指定该位相应的中断源处理模式(IRQ还是FIQ)。若某位为0,则该位相对应的中断按IRQ模式处理,为1则以FIQ模式进行处理,该寄存器初始化值为0x00000000,即所有中断皆以IRQ模式进行处理。(详细请参考s3c2410操作手册)。INTMSK/INTSUBMSK寄存器为中断屏蔽寄存器,INTMSK为主中断屏蔽寄存器,INTSUBMSK为副中断屏蔽寄存器。INTMSK有效位为32,INTSUBMSK有效位为11,这两个寄存器各个位与SRCPND和SUBSRCPND分别对应。它们的作用是决定该位相应的中断请求是否被处理。若某位被设置为1,则该位相对应的中断产生后将被忽略(CPU不处理该中断请求),设置为0则对其进行处理。这两个寄存器初始化后的值是0xFFFFFFFF和0x7FF,既默认情况下所有的中断都是被屏蔽的。到目前为止我们总共讲解了SRCPND,INTMOD,INTMSK,SUBSRCPND,INTSUBMSK五个寄存器,在继续讲解PRIORITY寄存器之前我们先来看一张图。先弄清楚一点,现在要讨论的是一个中断优先级的判断问题。为什么会有中断有先级的问题呢?我们知道CPU某个时刻只能对一个中断源进行中断处理,如果现在有3个中断同时发生了,那CPU要按什么顺序处理这个3个中断呢?这正是引入优先级判断的原因所在,通过优先级判断,CPU可以按某种顺序逐个处理中断请求。3sc2410的优先级判断分为两级。如上图所示,SRCPND寄存器对应的32个中断源总共被分为6个组,每个组由一个ARBITER(0~5)寄存器对其进行管理。中断必须先由所属组的ARBITER(0~5)进行第一次优先级判断(第一级判断)后再发往ARBITER6进行最终的判断(第二级判断)。ARBITER(0~5)这六个组的优先级已经固定,我们无法改变,也就是说由ARBITER0控制的该组中断优先级最高(该组产生的中断进行第一级判断后永远会以REQ0向ARBITER6传递过去)其次是ARBITER1,ARBITER2,ARBITER4,ARBITER4,ARBITER5.我们能够控制的是某个组里面各个中断的优先级顺序。怎么控制?通过PRIORITY寄存器进行控制:]以下是PRIORITY寄存器各个位的参数表从表上我们可以知道PRIORITY寄存器内部各个位被分为两种类型,一种是ARB_MODE,另一种为ARB_SEL,ARB_MODE类型有5组对应ARBITER(2~6),ARB_SEL类型有7组对应ARBITER(0~6)。现在我将以ARBITER2为例,讲解中断组与PRIORITY寄存器中ARB_SEL,ARB_MODE之间的相互关系。首先我们看到ARBITER2寄存器管理的该组中断里包括了6个中断,分别是INT_TIMER0,INT_TIMER1,INT_TIMER2,INT_TIMER3,INT_TIMER4,INT_UART2,她们的默认中断请求号分别为REQ0,REQ1,REQ2,REQ3,REQ4,REQ5。我们先看PRIORITY寄存器中的ARB_SEL2,该参数由两个位组成,初始值为00。从该表可以看出00定义了一个顺序0-1-2-3-4-5,这个顺序就是这组中断组的优先级排列,这个顺序指明了以中断请求号为0(REQ0)的INT_TIMER0具有最高的中断优先级,其次是INT_TIMER1,INT_TIMER2…。假设现在ARB_SEL2的值被我们设置为01。则一个新的优先级次序将被使用,01对应的优先级次序为0-2-3-4-1-5,从中可以看出优先级最高和最低的中断请求和之前没有变化,但本来处于第2优先级的INT_TIMER1中断现在变成了第5优先级。从ARB_SEL2被设置为00,01,10,11各个值所出现的情况我们可以看出,除最高和最低的优先级不变以外,其他各个中断的优先级其实是在做一个旋转排列(rotate)。为了达到对各个中断平等对待这一目标,我们可以让优先级次序在每个中断请求被处理完之后自动进行一次旋转,如何自动让它旋转呢?我们可以通过ARB_MODE2达到这个目的,该参数只有1个bit,置1代表开启对应中断组的优先级次序旋转,0则为关闭。事实上当该位置为1之后,每处里完某个组的一个中断后,该组的ARB_SEL便递增在1(达到11后恢复为00)。现在我们另ARB_MODE2=1,ARB_SEL2=00则当前ARBITER2的优先级顺序为0-1-2-3-4-5,假设现在该组的1号中断请求INT_TIMER1和2号中断请求INT_TIMER2被同时触发,CPU根据优先级判断后决定先把INT_TIMER1中断向ARBITER6进行发送(在ARBITER6做第最终优先级判断),接着再向ARBITER6发送INT_TIMER2中断。请注意,在INT_TIMER1被处理完毕后,该组中段的优先级次序被自动做了一次旋转,旋转后ARBITER2的优先级顺序变为0-2-3-4-1-5。假设之后某个时刻该组的INT_TIMER1和INT_TIMER2又被同时触发,则此时CPU优先处理的会是INT_TIMER2。若我们另ARB_MODE2=0,则改组的中断优先级次序在任何情况下都不做任何改变,除非我们人为地重新设置了ARB_SEL2的值。呼。。。好累。。。终于说完了麻烦的优先级-_-…继续。。。INTPND寄存器可能是整个中断处理过程中我们要特别注意的一个寄存器了,他的操作比较特别,怎么特别?请听我慢慢道来.:]先看一下该寄存器各位详细功能列表正如你所见的,INTPND寄存器与SRCPND长得一模一样,但他们在中断异常处理中却扮演着不同的角色,如果说SRCPND是中断信号进入中断处理模块后所经过的第一个场所的话,那么INTPND则是中断信号在中断处理模块里经历的最后一个寄存器。它的每个位对应一个中断请求,若该位被置1,则表示相应的中断请求被触发,描述到这里你可能会发现它不仅和SRCPND长得一模一样,就连功能都一样,其实不然,他们在功能上有着重大的区别。SRCPND是中断源引脚寄存器,某个位被置1表示相应的中断被触发,但我