以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);
}