IRQ中断服务函数
什么是IRQ中断服务函数?
IRQ中断服务函数是由操作系统或开发人员编写的函数,当IRQ中断请求到达服务器时,处理器会暂停当前任务,保存上下文,并跳转到相应的中断服务函数执行对应操作。
IRQ中断服务函数一般执行流程
保存上下文->中断处理操作->恢复上下文
IRQ中断服务函数实例
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
这串IRQ中断代码主要是区分当前发生的事什么中断(用中断ID号来区分),然后根据不同的中断做出不同的处理。
前四行的push即为保护现场,接下来三行为获取当前中断号,中断号被保存在了r0寄存器中,进入svc模式后,就可允许其他中断再次进入,这时,调用system_irqhandler函数(这是一个C语言函数,有一个参数),使用blx传递参数到C语言函数。后面就是恢复寄存器的操作了。总的来说,这个IRQ中断函数就是用中断号判断属于哪个中断,然后将中断号作为参数传递给中断处理函数(C语言函数),具体的不同操作就将在C函数里进行编写完成。