1.6.6. int_return

1
#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_Handle2		        @ call the isr
int_return:
	ldmia	sp!, 	{ r0-r12,pc }^	@ return from interrupt
	.align	5
fiq:3
	get_fiq_stack
	/* someone ought to write a more effiction fiq_save_user_regs */
	irq_save_user_regs
	bl 	do_fiq4
	irq_restore_user_regs
#else
5
	.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
        

1

此处,做的事情,很容易看懂,就是中断发生后,掉转到这里,然后保存对应寄存器,然后跳转到对应irq函数IRQ_Handle中去。

但是前面为何sp为何去减去4,原因不太懂。

2

关于IRQ_Handle,是在:

u-boot-1.1.6_20100601\opt\EmbedSky\u-boot-1.1.6\cpu\arm920t\s3c24x0\interrupts.c

中:

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。

3

此处也很简单,就是发生了快速中断FIQ的时候,保存IRQ的用户模式寄存器,然后调用函数do_fiq,调用完毕后,再恢复IRQ的用户模式寄存器。

4

do_fiq()是在:

u-boot-1.1.6_20100601\opt\EmbedSky\u-boot-1.1.6\cpu\arm920t\interrupts.c

中:

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而已。

5

此处就是,如果没有定义CONFIG_USE_IRQ,那么就用这段代码,可以看到,都只是直接调用do_irq和do_fiq,也没做什么实际工作。