经过自学,然后又系统的学习,写一点ARM44b的中断总结。中断:首先进行中断控制等寄存器的设置,然后主要是中断响应流程。
当中断发生是,处理器会自动跳转到从0x0地址开始的异常中断矢量表中的某个位置(由异常类型确定)跳转后读取指令然后运行。比如:IRQ中断发生,一定跳到0x18地址,b IRQ ;
当中断发生是,主要是中断服务函数的地址怎么装到PC指针中的,通常在中断初始化时会有:pISR_EINT3=(int)EXT3_Exception;这样一条指令,就是把EXT3_Exception()这样一个ISR的地址装到pISR_EINT3中;然后pISR_EINT3指针就是外部中断3的地址:
#define pISR_EINT3 (*(unsigned *)(_ISR_STARTADDRESS+0x78))
现在要看_ISR_STARTADDRESS+0x78代表是什么含义,首先看这样一个#define宏中(unsigned *)(_ISR_STARTADDRESS+0x78)是一个地址,这个地址在ram中的位置就是根据下面程序的地址,当中断发生时硬件会自动跳转到这个地址,执行地址中的程序,即把ISR函数的地址传给PC执行中断程序。
^ _ISR_STARTADDRESS
HandleReset # 4
HandleUndef # 4
HandleSWI # 4
HandlePabort # 4
HandleDabort # 4
HandleReserved # 4
HandleIRQ # 4
HandleFIQ # 4
;Do not use the label 'IntVectorTable',
;because armasm.exe can not recognize this label correctly.
;the value is different with an address you think it may be.
;IntVectorTable
HandleADC # 4
HandleRTC # 4
HandleUTXD1 # 4
HandleUTXD0 # 4
HandleSIO # 4
HandleIIC # 4
HandleURXD1 # 4
HandleURXD0 # 4
HandleTIMER5 # 4
HandleTIMER4 # 4
HandleTIMER3 # 4
HandleTIMER2 # 4
HandleTIMER1 # 4
HandleTIMER0 # 4
HandleUERR01 # 4
HandleWDT # 4
HandleBDMA1 # 4
HandleBDMA0 # 4
HandleZDMA1 # 4
HandleZDMA0 # 4
HandleTICK # 4
HandleEINT4567 # 4
HandleEINT3 # 4
HandleEINT2 # 4
HandleEINT1 # 4
HandleEINT0 # 4 ;0xc1(c7)fff84
从以上程序可以看到给HandleEINT3 # 4分配的地址为_ISR_STARTADDRESS+30*4,即_ISR_STARTADDRESS+0x78;它是和pISR_EINT3的地址相同。就把ISR函数的首地址放到了这个分配的地址。最后把ISP赋值给PC: ldmfd sp!,{r8-r9}
add sp,sp,#4
subs pc,lr,#4
还有一个问题,就是中断向量的偏移是怎么算出来的:主要是用以下程序来计算r8中会根据I_ISPR中的内容计算出外部中断3相对于_ISR_STARTADDRESS的偏移量,本例中r8=0x78;
IsrIRQ ;using I_ISPR register.
sub sp,sp,#4 ;reserved for PC
stmfd sp!,{r8-r9}
;IMPORTANT CAUTION
;if I_ISPC is not used properly, I_ISPR can be 0 in this routine.
ldr r9,=I_ISPR
ldr r9,[r9]
cmp r9, #0x0 ;If the IDLE mode work-around is used,
;r9 may be 0 sometimes.
beq %F2
mov r8,#0x0
0
movs r9,r9,lsr #1
bcs %F1
add r8,r8,#4
b %B0
1
ldr r9,=HandleADC
add r9,r9,r8
ldr r9,[r9]
str r9,[sp,#8]
ldmfd sp!,{r8-r9,pc}
2
ldmfd sp!,{r8-r9}
add sp,sp,#4
subs pc,lr,#4