以s3c2440为例讲述,中断处理流程:
1.开中断。产生外部中断。流程如下按键----->中断控制器------->cpu(总开关)
* 按键:
需要设置GPIO为中断模式,上升沿还是下降沿触发。
* 中断控制器:
* cpu:
2.中断处理
* 跳转到中断向量表。如果从nandflash启动,代码已经重定位到sdram,此时候是绝对跳转,会跳转的真正的0地址(sram)。
中断向量表如下:
* 硬件操作 a. lr_irq保存有被中断模式中的下一条即将执行的指令的地址 b. SPSR_irq保存有被中断模式的CPSR c. CPSR中的M4-M0被设置为10010, 进入到irq模式 d. 跳到0x18的地方执行程序
*软件操作
a. 设置sp_irq栈,这个是irq模式的sp,sp_user不用了,两个是独立的sp,所以需要重新设置。
b.保存现场 /* 在irq异常处理函数中有可能会修改r0-r12, 所以先保存 */ /* lr-4是异常处理完后的返回地址, 也要保存 */ 方便最后pc =lr,可以从异常模式跳转到用户模式
c.处理irq异常
跳转到中断处理函数
d.恢复现场。
代码如下:
中断向量表:
.text .global _start _start: b reset /* vector 0 : reset */ ldr pc, und_addr /* vector 4 : und */ ldr pc, swi_addr /* vector 8 : swi */ b halt /* vector 0x0c : prefetch aboot */ b halt /* vector 0x10 : data abort */ b halt /* vector 0x14 : reserved */ ldr pc, irq_addr /* vector 0x18 : irq */ b halt /* vector 0x1c : fiq */ und_addr: .word do_und swi_addr: .word do_swi irq_addr: .word do_irq中断处理及跳转:
.align 4 do_irq: /* 执行到这里之前: * 1. lr_irq保存有被中断模式中的下一条即将执行的指令的地址 * 2. SPSR_irq保存有被中断模式的CPSR * 3. CPSR中的M4-M0被设置为10010, 进入到irq模式 * 4. 跳到0x18的地方执行程序 */ /* sp_irq未设置, 先设置它 */ ldr sp, =0x33d00000 /* 保存现场 */ /* 在irq异常处理函数中有可能会修改r0-r12, 所以先保存 */ /* lr-4是异常处理完后的返回地址, 也要保存 */ sub lr, lr, #4 stmdb sp!, {r0-r12, lr} /* 处理irq异常 */ bl handle_irq_c /* 恢复现场 */ ldmia sp!, {r0-r12, pc}^ /* ^会把spsr_irq的值恢复到cpsr里 */中断处理函数:
void handle_irq_c(void) { /* 分辨中断源 */ int bit = INTOFFSET; /* 调用对应的处理函数 */ irq_array[bit](bit); //函数指针数组, /* 清中断 : 从源头开始清 */ SRCPND = (1<<bit); INTPND = (1<<bit); }