IRQ_Handler:
push {lr} /* 保存 lr 地址 */
push {r0-r3, r12} /* 保存 r0-r3,r12 寄存器 */
mrs r0, spsr /* 读取 spsr 寄存器 */
push {r0} /* 保存 spsr 寄存器 */
mrc p15, 4, r1, c15, c0, 0 /* 将 CP15 的 C0 内的值到 R1 寄存器中
* 参考文档 ARM Cortex-A(armV7)编程手册 V4.0.pdf P49
* Cortex-A7 Technical ReferenceManua.pdf P68 P138
*/
add r1, r1, #0X2000 /* GIC 基地址加 0X2000,得到 CPU 接口端基地址 */
ldr r0, [r1, #0XC] /* CPU 接口端基地址加 0X0C 就是 GICC_IAR 寄存器,
* GICC_IAR 保存着当前发生中断的中断号,我们要根据
* 这个中断号来绝对调用哪个中断服务函数
*/
push {r0, r1} /* 保存 r0,r1 */
cps #0x13 /* 进入 SVC 模式,允许其他中断再次进去 */
push {lr} /* 保存 SVC 模式的 lr 寄存器 */
ldr r2, =system_irqhandler /* 加载 C 语言中断处理函数到 r2 寄存器中*/
blx r2 /* 运行 C 语言中断处理函数,带有一个参数 */
pop {lr} /* 执行完 C 语言中断服务函数,lr 出栈 */
cps #0x12 /* 进入 IRQ 模式 */
pop {r0, r1}
str r0, [r1, #0X10] /* 中断执行完成,写 EOIR */
pop {r0}
msr spsr_cxsf, r0 /* 恢复 spsr */
pop {r0-r3, r12} /* r0-r3,r12 出栈 */
pop {lr} /* lr 出栈 */
subs pc, lr, #4 /* 将 lr-4 赋给 pc */
栈空间为:
此时栈空间为:
此时栈空间为(注意栈空间里面的只是值不是r0r1寄存器,是寄存器的值):
此时栈空间为:
此时栈空间为
此时栈空间为
此时栈空间为: