一般情况下,IRQ中断发生后,系统会在距程序入口0x00000018处执行 B HandlerIRQ HandlerIRQ处的代码是 HandlerIRQ HANDLER HandleIRQ 它使用了一个名为HANDLER的宏,此宏扩展后为: SUB SP, SP, #4 ; SP=SP-4,此地址用于存放转跳地址,也即中断程序的入口地址 STMFD SP!, {R0} ; 把工作寄存器R0压入栈,sp=SP-4(sp先减) LDR R0, =HandleIRQ ; 将HandleIRQ的值放入r0 LDR R0, [R0] ; 把HandleIRQ的值所指向的内容(也就是中断程序的入口地址)放入R0 STR R0, [SP,#4] ; 通过R0把中断服务程序(ISR)入口地址压入栈的sp=SP+4处 LDMFD SP!, {R0,pc} 如注释所讲,此段代码的作用是跳转到HandleIRQ地址处存放的值所指向的代码,那么HandleIRQ地址处存放的值是哪段代码的起始地址呢,启动代码中还有这么一段: LDR R0, =HandleIRQ ; IRQ异常向量的绝对地址->R0 LDR R1, =IsrIRQ ; R1 = 二级向量表的中断查询例程IsrIRQ的绝对地址 STR R1, [R0] 也就是说,HandleIRQ地址处存放的标号IsrIRQ的地址,程序将跳转到IsrIRQ标号处的代码接着执行,IsrIRQ标号处的代码是: SUB SP, SP, #4 ; reserved for PC,SP=SP-4 STMFD SP!, {R8-R9} ; SP=SP-8 LDR R9, =INTOFFSET ; 把INTOFFSET寄存器的值装入R9,其值指向的存储地址存着中断的 ; 偏移量(以字为单位,即4字节,见P14-16) LDR R9, [R9] ; 中断的偏移量装入R9 LDR R8, =HandleEINT0 ; 将HandleEINT0装入R8,其值为二级向量表的入口地址 ADD R8, R8, R9, lsl #2 ; R8=R8+R9*4 LDR R8, [R8] ; 将所要的中断处理程序的入口地址装入R8 STR R8, [SP,#8] ; SP=SP+8,将中断处理程序的入口地址推入堆栈 LDMFD SP!, {R8-R9,pc} ; 出线,R8,R9还原其值,将中断处理程序的入口地址装入pc 这段代码的作用是使程序跳转到 HandleEINT0标号地址+INTOFFSET*4 的地址处,该地址是真正的中断处理程序的入口地址。HandleEINT0是中断向量表的入口地址,这其实是根据INTOFFSET寄存器的值在进行查表,INTOFFSET寄存器的值指示所发生的中断的类型,它由硬件控制。中断处理程序一般在C程序中定义,在MDK中可由下面的写法来定义 void __irq 函数名(参数列表) 要记得将此函数地址保存在中断向量表中: 向量表相应地址 = (unsigned)函数名; 此向量表相应地址可用一个符号来表示,以增加可读性,此符号可如此定义: 符号 EQU (向量表相应地址) 在中断处理程序中要记得将SRCPND和INTPND寄存器的相应位清零以清除挂起状态,否则会不断重复执行此中断处理程序,清零的方法是往相应位写1,而不是写0。
S3C2440A中断小记
最新推荐文章于 2022-02-23 15:02:25 发布