Reset,Undefined instruction,Software Interrupt,Abort (prefetch),Abort (data),Reserved,IRQ,FIQ
下面是某个采用低端模式的系统源码片段:
b Handle_Reset
b HandleUndef
b HandleSWI
b HandlePrefetchAbort
b HandleDataAbort
b HandleNotUsed
b HandleIRQ
b HandleFIQ
…..
…
..
other codes
…
上面这部分片段一般出现在一个名叫“head.s”的汇编文件里,“b Handle_Reset”这条语句就是系统上电之后运行的第一条语句。也就是说这部分代码的二进制码必须位于内存的最开始部分(这正是低端存放模式), 因为上电后CPU会从SDRAM的0x00000000处取第一条指令并执行。
0x00000000: b Handle_Reset
0x00000004: b HandleUndef
0x00000008: b HandleSWI
0x0000000C: b HandlePrefetchAbort
0x00000010: b HandleDataAbort
0x00000014: b HandleNotUsed
0x00000018: b HandleIRQ
0x0000001C: b HandleFIQ
上面是该程序段在系统上电后加载到内存后的分布情况,我们可以看到每条指令占用了4个字节。
s3c2410的中断异常处理模块总共由以下寄存器构成
SRCPND(SOURCE PENDING REGISTER)
INTMOD(INTERRUPT MODE REGISTER)
INTMSK(INTERRUPT MASK REGISTER)
PRIORITY( PRIORITY REGISTER)
INTPND(INTERRUPT PENDING REGISTER)
INTOFFSET(INTERRUPT OFFSET REGISTER)
SUBSRCPND (INTERRUPT SUB SOURCE PENDING)
INTSUBMSK (INTERRUPT SUB MASK REGISTER)
下面我将讲解每个寄存器在一个中断处理流程中所扮演的角色:
SRCPND/ SUBSRCPND这两个寄存器在功能上是相同的,它们是中断源引脚寄存器,在一个中断异常处理流程中,中断信号传进中断异常处理模块后首先遇到的就是SRCPND/ SUBSRCPND,这两个寄存器的作用是用于标示出哪个中断请求被触发。SRCPND的有效位为32,SUBSRCPND 的有效位为11,它们中的每一位分别代表一个中断源。SRCPND为主中断源引脚寄存器,SUBSRCPND为副中断源引脚寄存器。
这里列举出SRCPND的各个位信息:
每个位的初始值皆为0。假设现在系统触发了TIMER0中断,则第10bit将被置1,代表TIMER0中断被触发,该中断请求即将被处理(若该中断没有被屏蔽的话)。SUBSRCPND情况与SRCPND相同,这里就不多讲了。
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的优先级判断分为两级。
以下是PRIORITY寄存器各个位的参数表
从表上我们可以知道PRIORITY寄存器内部各个位被分为两种类型,一种是ARB_MODE,另一种为ARB_SEL, ARB_MODE类型有5组对应ARBITER(2~6)(PS:此处应更正为ARB_MODE类型有7组对应ARBITER(0~6),在datasheet中上表还有续表,为ARB_MODE1-0),ARB_SEL类型有7组对应ARBITER(0~6)。现在我将以ARBITER2为例,讲解中断组与PRIORITY寄存器中ARB_SEL, ARB_MODE之间的相互关系。
现在我们另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表示相应的中断被触发,但我们知道在同一时刻内系统可以触发若干个中断,只要中断被触发了,SRCPND的相应位便被置1,也就是说SRCPND在同一时刻可以有若干位同时被置1,然而INTPND则 不同,他在某一时刻只能有1个位被置1,INTPND 某个位被置1(该位对应的中断在所有已触发的中断里具有最高优先级且该中断没有被屏蔽),则表示CPU即将或已经在对该位相应的中断进行处理。于是我们可 以有一个总结:SRCPND说明了有什么中断被触发了,INTPND说明了CPU即将或已经在对某一个中断进行处理。
SRCPND="0x00000002" //位0被置为0
INTPND =0x00000001 //位0被置为0(方法是往该位写入1)
INTOFFSET寄存器的功能则很简单,它的作用只是用于表明哪个中断正在被处理。下面是该寄存器各位详细功能列表
现在我把整个中断流程用一个图加以说明
以上这个图清楚地说明了一个中断异常处理流程。
假设2:PRIORITY寄存器中ARB_MODE2,ARB_MODE5皆为0,既不进行优先级的自动旋转排序,任何时候
ARBITER2,ARBITER5控制的中断组优先级次序分别为0-1-2-3-4-5和1-2-3-4。
假设3:这三个中断皆为IRQ类型。
假设4:这三个中断同时被触发。
INT_TIMER0,INT_TIMER2和INT_UART0三个中断被同时触发,此时三个中断信号流向SRCPND寄存器,使该寄存器中的第10位,12位,28位被置为1,中断信号继续向前流经INTMASK寄存器,这三个中断都没有被屏蔽,于是信号进一步流经INTMODE寄存器,这三个中断皆为IRQ类型,故中断信号继续向前流向PRIORITY寄存器,经过优先级判断,INT_TIMER0中断信号使INTPND寄存器的第10位置1(INT_TIMER0优先级最高),此时INTOFFSET寄存器的值为10,CPU转向相应的中断服务例程进行处理。处理完毕后,我们的程序将INTPND和SRCPND的第10置为0,至此INT_TIMER0中断处理完毕。此时SRCPND的第12位,28位仍为1(这两个中断请求未被处理),故他们会继续被CPU已刚才描述的方式进行处理。
中断异常处理就先讲到这吧 :]
以上是原帖内容,再次感谢作者。。。
PS:
在对2410的裸板进行中断实验的过程中,从菜鸟的角度出发,我把学到了一些东西和之前ARM体系结构的理论结合起来:
1、在ARM处理器中,r13(sp)和r14(lr)分别对应6个不同状态下的物理寄存器,其中1个是用户、系统模式共用的,其他分别对应5种异常模式 (Exception Mode)。要在后续程序中使用中断,则应先把要用到的各种模式的堆栈设置好,如设置IRQ和系统模式的sp:
ldr sp, =0x33000000
msr cpsr_c, #0xdf @进入系统模式,IRQ和FIQ都处于禁止状态
ldr sp, =0x34000000
bl init_irq @初始化中断
msr cpsr_r, #0x5f @置控制域的I位为0,打开irq中断。实验中只用到irq