ARM920T 的异常向量表有两种存放方式,一种是低端存放(从0x00000000处开始存放),另一种是高端存放(从0xfff000000处开始存放)。关于为什 么要分两种方式进行存放这点我将在介绍MMU的文章中进行说明,本文采用低端模式。ARM920T能处理有8个异常,他们分别是:
Reset,Undefined instruction,Software Interrupt,Abort (prefetch),Abort (data),Reserved,IRQ,FIQ
下面是某个采用低端模式的系统源码片段:
|
上面这部分片段一般出现在一个名叫“head.s”的汇编文件里,“b Handle_Reset”这条语句就是系统上电之后运行的第一条语句。也就是说这部分代码的二进制码必须位于内存的最开始部分(这正是低端存放模式), 因为上电后CPU会从SDRAM的0x00000000处取第一条指令并执行。
|
上面是该程序段在系统上电后加载到内存后的分布情况,我们可以看到每条指令占用了4个字节。
上电后,PC指针会跳转到Handle_Reset处开始运行。以后系统每当有异常出现,则CPU会根据异常号,从内存的0x00000000处开始查表 做相应的处理,比如系统触发了一个IRQ异常,IRQ为第6号异常,则CPU将把PC指向0x00000018地址 (4*6=24=0x00000018)处运行,该地址的指令是跳转到“中断异常服务例程”(HandleIRQ)处运行。以上就是我对异常向量表的一个 简单介绍。现在可以进入我们文章的主题 “中断异常处理”,s3c2410的中断分快中断(FIQ)和普通中断(IRQ),我们讨论的重点是普通中断(IRQ)。
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 相同,这里就不多讲了。(PS:SUBSRCPND寄存器的作用是对SRCPND寄存器的补充,因为ARM的寄存器是32位的,但是中断是不止这么多的,比如说INT_UART0,它就对应了SUBSRCPND寄存器的三个中断,分别是
UART0 error interrupt, UART0 transmit interrupt, UART0 receive interrupt, 而这三个中断分别对应SUBSRCPND的第0,1,2三位 )
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 寄存器对应的32个中断源总共被分为6个组,每个组由一个 ARBITER(0~5) 寄存器对其进行管理。中断必须先由所属组的 ARBITER(0~5) 进行第一次优先级判断(第一级判断)后再发往 ARBITER6 进行最终的判断(第二级判断)。 ARBITER(0~5) 这六个组的优先级已经固定,我们无法改变,( PS:这里有跟作者意见不一样的地方,ARBITER0-5 的优先级并不是固定的,ARBITER6 就是控制ARBITER0-5 的优先级顺序的,我们可以看PRIORITY 寄存器的ARB_SEL6 ,如果是00b的话,那当然就是ARBITER0 > ARBITER1 > ARBITER 2 > ARBITER3 > ARBITER4 > ARBITER5 ,但如果ARB_SEL6是 01b的话,那就是0 >2>3>4>1>5了,这样的设计可以完善我们的优先级控制机制 )也就是说由 ARBITER0 控制的该组中断优先级最高(该组产生的中断进行第一级判断后永远会以REQ0向 ARBITER6 传递过去)其次是 ARBITER1, ARBITER2, ARBITER4, ARBITER4, ARBITER5 .我们能够控制的是某个组里面各个中断的优先级顺序。怎么控制?通过 PRIORITY 寄存器进行控制:]
现在我们另 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 寄存器可能是整个中断处理过程中我们要特别注意的一个寄存器了,他的操作比较特别,怎么特别?请听我慢慢道来.:]
先看一下该寄存器各位详细功能列表
特别注意:每当某一个中断被处理完之后,我们必须 手动地把SRCPND/SUBSRCPND , INTPND 三个寄存器中与该中断相应的位由1设置为0 ,刚才我说 INTPND 的操作很特别,它的特别之处就在于对当我们要把该寄存器中某个值为1的位设置为0时,我们不是往该位置0,而是 往该位置1 。假设 SRCPND=0x00000003,INTPND=0x00000001 ,该值说明当前0号中断和1号中断被触发,但当前正在被处理的是0号中断,处理完毕后我们应该这样设置 INTPND和SRCPND :
SRCPND="0x00000002" //位0被置为0
INTPND =0x00000001 //位0被置为0( 方法是往该位写入1 )
INTOFFSET 寄存器的功能则很简单,它的作用只是用于表明哪个中断正在被处理。下面是该寄存器各位详细功能列表
现在我把整个中断流程用一个图加以说明
下面我用INT_TIMER0, INT_TIMER2和INT_UART0三个中断完整地介绍一次中断异常处理。首先我们得做几个假设:
假设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 :
|
2、 如果用到按键等中断控制,是属于外部中断的( External Interrupt ),就需要配置 EINT 相关的寄存器。