#ifdef CONFIG_USE_IRQ .align 5 irq: /* add by www.embedsky.net to use IRQ for USB and DMA */ sub lr, lr, #4 @ the return address ldr sp, IRQ_STACK_START @ the stack for irq stmdb sp!, { r0-r12,lr } @ save registers ldr lr, =int_return @ set the return addr ldr pc, =IRQ_Handle @ call the isr int_return: ldmia sp!, { r0-r12,pc }^ @ return from interrupt .align 5 fiq: get_fiq_stack /* someone ought to write a more effiction fiq_save_user_regs */ irq_save_user_regs bl do_fiq irq_restore_user_regs #else .align 5 irq: get_bad_stack bad_save_user_regs bl do_irq .align 5 fiq: get_bad_stack bad_save_user_regs bl do_fiq #endif
此处,做的事情,很容易看懂,就是中断发生后,掉转到这里,然后保存对应寄存器,然后跳转到对应irq函数IRQ_Handle中去。 但是前面为何sp为何去减去4,原因不太懂。 | |
关于IRQ_Handle,是在:
中: void IRQ_Handle(void) { unsigned long oft = intregs->INTOFFSET; S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO(); // printk("IRQ_Handle: %d\n", oft); //清中断 if( oft == 4 ) gpio->EINTPEND = 1<<7; intregs->SRCPND = 1<<oft; intregs->INTPND = intregs->INTPND; /* run the isr */ isr_handle_array[oft](); } 此处细节就不多解释了,大体含义是,找到对应的中断源,然后调用对应的之前已经注册的中断服务函数ISR。 | |
此处也很简单,就是发生了快速中断FIQ的时候,保存IRQ的用户模式寄存器,然后调用函数do_fiq,调用完毕后,再恢复IRQ的用户模式寄存器。 | |
do_fiq()是在:
中: void do_fiq (struct pt_regs *pt_regs) { printf ("fast interrupt request\n"); show_regs (pt_regs); bad_mode (); } 和前面提到过的do_undefined_instruction的一样,就是打印寄存器信息,然后跳转到bad_mode()去重启CPU而已。 | |
此处就是,如果没有定义CONFIG_USE_IRQ,那么就用这段代码,可以看到,都只是直接调用do_irq和do_fiq,也没做什么实际工作。 |