ARM的中断分析
对于学习ARM的朋友来说,中断处理是一块硬骨头,尤其是中断向量表以及中断的跳转。下面主要对中断向量表的建立问题及重映射问题进行探讨。近来做一些东西用到中断时,总会出现一些问题。
各种Bootloader的初始化相关代码摘要,首先来看下面的程序: ^ DRAM_BASE //DRAM的基地址HandleReset # 4 // 空留4个单元HandleUndef # 4HandleSwi # 4HandlePrefetch # 4 //用于填充地址的HandleAbort # 4HandleReserv # 4HandleIrq # 4HandleFiq # 4 注: 这里的^是RMAP,#是FIELD,分配的意思 就是在SDARM的BANK0开始的地方定义了一个中断向量表,相当于0地址的FLASH。空留单元用于存放中断程序的入口地址。ExceptionHandlerTable //实际的映射地址 DCD UserCodeArea DCD SystemUndefinedHandler DCD SystemSwiHandler DCD SystemPrefetchHandler DCD SystemAbortHandler DCD SystemReserv DCD SystemIrqHandler DCD SystemFiqHandler 这个表中存放的是汇编程序中中断处理函数的入口地址,每一项对应一个中断函数。这次的跳转后就进入了C服务程序。 从初始化程序的开始处来看:(各种Bootloader的初始化代码) AREA Init, CODE, READONLY //相当于init进程 ENTRY //入口 B Reset_Handler B Undefined_Handler //无条件的跳转 B SWI_Handler B Prefetch_Handler B Abort_Handler NOP Reserved vector B IRQ_Handler B FIQ_Handler FIQ_Handler SUB sp, sp, #4 STMFD sp!, {r0} FD满递减堆栈 执行寄存器压栈操作.LDR r0, =HandleFiq 汇编里的处理函数地址,然后跳到C中,在DRAM。LDR r0, [r0] 中断向量地址给R0. STR r0, [sp, #4] 中断向量地址给PC LDMFD sp!, {r0, pc}
稍微解释一下: 首先执行了压栈,然后给出了中断入口地址.这个HandleFiq就是我们前面的在DRAM中建立的中断向量其中一个的地址。在HandleFiq开始的四个字节中,放着汇编中断处理函数的入口地址。 那么汇编中断处理函数的地址是如何放到DRAM中断向量表里的呢? 上面的第一个表就起作用了。看下面这段程序: EXCEPTION_VECTOR_TABLE_SETUP LDR r0, =HandleReset LDR r1, =ExceptionHandlerTable MOV r2, #8 ExceptLoop LDR r3, [r1], #4 STR r3, [r0], #4 SUBS r2, r2, #1 //填充8个地址 BNE ExceptLoop //从表里取出来给了HandleReset后面的空间 这一段把ExceptionHandlerTable里的中断处理函数的地址拷给了SDRAM里的中断向量表。这样两者就联系起来了。 在执行程序开始的跳转之后就自然跳到了*****Handler.真正的处理函数如下: 它实际上只调用了C语言的中断处理函数,其他什么也没做。SystemFiqHandler IMPORT ISR_FiqHandler STMFD sp!, {r0-r7, lr} BL ISR_FiqHandler //真正的中断处理服务函数 LDMFD sp!, {r0-r7, lr} SUBS pc, lr, #4 它实际上只调用了C语言的中断处理函数,其他什么也没做。写中断处理服务程序其实就只写C中相应的处理部分就好了。
void ISR_FiqHandler(void){ IntOffSet = (U32)INTOFFSET; (IntOffSet>>2) (*InterruptHandlers[IntOffSet>>2])(); // Call interrupt service routine}
其实就是将中断向量表重映射,以提高中断的响应速度。代码在SDRAM的运行速度要比在FLASH中运行速度快。
|