|
关于中断大体可以这样理解:处理器内核有两个中断接口FIQ(快速中断请求)和IRQ(标准中断请求),而片内高级中断控制器利用这两个接口
将外设的中断请求有序的传递到内核。

而如何将多达32个中断请求只用两根线传递到内核呢?这是借助硬件软件两方面的分发处理来完成的。首先AIC为每一个外设或中断源提供了一个
中断源向量寄存器(AIC_SVR0~AICSVR31),在配置使能相应外设时用户将设备的中断处理函数地址存入对应的源向量寄存器,而当中断请求发生时
AIC将对应的源向量寄存器中的地址复制到中断向量寄存器(AIC_IVR)并向内核发出IRQ请求。以上是硬件实现的中断分发过程,然而在用户程序中
也必须做相关处理才能完成IRQ的分发处理,对于内核来讲IRQ只是一个中断向量,当IRQ中断请求时内核会跳到一个固定的地址(即IRQ向量)处理
中断,用户程序(ARM的启动代码)必须在这个IRQ中断程序中分发处理才能分辨不同的设备的中断请求,但有了上面这样硬件的预处理过程,软件分
发处理变得比较简单,跳到AIC中断向量寄存器中地址处即可,下面具体看一下启动代码:
PROGRAM
?RESET
RSEG INTRAMSTART_REMAP
RSEG INTRAMEND_REMAP
RSEG ICODE:CODE:ROOT(2)
CODE32 ; Always ARM mode after reset
org 0
reset
B InitReset ; 0x00 Reset handler
undefvec:
B undefvec ; 0x04 Undefined Instruction
swivec:
B swivec ; 0x08 Software Interrupt
pabtvec:
B pabtvec ; 0x0C Prefetch Abort
dabtvec:
B dabtvec ; 0x10 Data Abort
rsvdvec:
B rsvdvec ; 0x14 reserved
irqvec:
;此处是IRQ向量,它是固定的地址
B IRQ_Handler_Entry ; 0x18 IRQ
fiqvec: ; 0x1c FIQ
FIQ_Handler_Entry:
................................
;此处代码省略未列出
IRQ_Handler_Entry:
;IRQ处理例程
;- Manage Exception Entry
;- Adjust and save LR_irq in IRQ stack
sub lr, lr, #4
stmfd sp!, {lr}
;- Save SPSR need to be saved for nested interrupt
mrs r14, SPSR
stmfd sp!, {r14}
;- Save and r0 in IRQ stack
stmfd sp!, {r0}
;- Write in the IVR to support Protect Mode
;- No effect in Normal Mode
;- De-assert the NIRQ and clear the source in Protect Mode
ldr r14, =AT91C_BASE_AIC
ldr r0 , [r14, #AIC_IVR]
str r14, [r14, #AIC_IVR]
;- Enable Interrupt and Switch in Supervisor Mode
msr CPSR_c, #ARM_MODE_SVC
;- Save scratch/used registers and LR in User Stack
stmfd sp!, { r1-r3, r12, r14}
;- Branch to the routine pointed by the AIC_IVR 跳到AIC_IVR寄存器内地址处,这便是软件分发处理过程
mov r14, pc
bx r0
;- Restore scratch/used registers and LR from User Stack
ldmia sp!, { r1-r3, r12, r14}
;- Disable Interrupt and switch back in IRQ mode
msr CPSR_c, #I_BIT | ARM_MODE_IRQ
;- Mark the End of Interrupt on the AIC
ldr r14, =AT91C_BASE_AIC
str r14, [r14, #AIC_EOICR]
;- Restore R0
ldmia sp!, {r0}
;- Restore SPSR_irq and r0 from IRQ stack
ldmia sp!, {r14}
msr SPSR_cxsf, r14
;- Restore adjusted LR_irq from IRQ stack directly in the PC
ldmia sp!, {pc}^
这样,我们就知道:某一片内外设使用了AIC的哪一个输入通道是与内核无关的,它与具体芯片厂家的设计有关。在AT91SAM7S中片内外设的ID号
便是AIC中断源向量寄存器AIC_SVRn的索引,例如定时器/计数器0的ID是12所以它的中断处理函数地址应存入AIC_SVR12中。AIC其它寄存器的配置也
是类似,一般都是设置设备ID对应位来配置相关功能。
FIQ(快速中断请求)很大程度上可以说是为了提供从芯片外通过FIQ引脚申请中断的一个快速通道。AIC将第一个中断源通道留给了FIQ,即FIQ
的用户中断程序入口地址应存入AIC_SVR0中以便在FIQ中断处理程序中调用。
FIQ_Handler_Entry:
;启动代码中快速中断的处理程序
;- Switch in SVC/User
Mode to allow User Stack access for C code
; because the FIQ is
not yet acknowledged
;- Save and r0 in
FIQ_Register
mov r9,r0
ldr r0 , [r8, #AIC_FVR]
msr CPSR_c,#I_BIT |
F_BIT | ARM_MODE_SVC
;- Save scratch/used
registers and LR in User Stack
stmfd sp!, { r1-r3,
r12, lr}
;- Branch to the
routine pointed by the AIC_FVR ;跳到用户设置的FIQ处理程序,AIC_FVR返回AIC_SVR0的值
mov r14, pc
bx r0
;- Restore
scratch/used registers and LR from User Stack
ldmia sp!, { r1-r3,
r12, lr}
;- Leave Interrupts
disabled and switch back in FIQ mode
msr CPSR_c, #I_BIT |
F_BIT | ARM_MODE_FIQ
;- Restore the R0
ARM_MODE_SVC register
mov r0,r9
;- Restore the Program
Counter using the LR_fiq directly in the PC
subs pc,lr,#4
相对于IRQ来讲FIQ是没有硬件分发机制的,但我们仍然可以通过设置AIC的快速强制使能寄存器(AIC_FFER)使普通外设中断变成快速中断,
如果中断源是多个那必须用软件实现分发(即进入FIQ中断后判断中断源)。通常快速中断是不这样使用的,它的中断源一般只有一个以达到
快速反应的目的。
芯艺设计室(http://www.chipart.cn) 2008.03.22 转载请注明出处!
|