问题分析:
在arm程序的开发过程中,对中断的处理是很普遍的、也是相当重要的。mdk-arm使用的rvct编译器提供了__irq关键字,用此关键字修饰的函数被作为中断出来函数编译,即在编译的过程中,编译器会自动添加中断处理过程中现场保护和恢复的代码,减小程序的开发难度,加快软件的开发过程。
在理解__irq关键字的作用之前,先看一下arm核对异常的处理过程。当产生异常时, arm核拷贝cpsr寄存器的内容spsr_
回指令如下:
? 从swi和undef异常返回时使用:
movs pc, lr;
? 从fiq、irq和预取终止返回时使用:
subs pc, lr,#4;
? 从数据异常返回时使用:
subs pc, lr,#8
在使用上述指令异常返回时,如果lr之前被压栈的话使用ldm “∧”, 例如:
ldmfd sp!, {pc}∧
问题解答:
理解了arm异常处理的过程以后,mdk-arm中__irq关键字的作用就容易理 解了。下面的函数为一个中断处理函数,其前面加了__irq关键字。
__irq void pwm0_irq_handler(void)
{
//deassert pwm0 interrupt signal
unsigned int i=at91f_pwmc_getinterruptstatus(at91c_base_pwmc);
// clear the led's. on the board we must apply a "1" to turn off leds
at91f_pio_setoutput(at91c_base_pioa, led_mask[0]);
at91f_pwmc_stopchannel(at91c_base_pwmc,at91c_pwmc_chid1);
at91f_aic_clearit(at91c_base_aic,at91c_id_pwmc);
at91f_aic_acknowledgeit(at91c_base_aic);
}
当编译器器编译这个函数时,除了保存atpcs规则规定的寄存器以外,还保存了cpsr及pc的值。在函数的返回时,还自动添加了subs pc, lr, #4和从spsr寄存器恢复cpsr寄存器值的指令。用这种方式处理以后,中断处理函数可以和普通函数一样的使用。
注意:中断处理都是在arm模式下进行的,当源程序欲编译成thumb指令时,这时,用__irq关键字修饰的函数仍然会被编译成arm指令。如果源程序编译成在cortex m3上运行的指令时,关键字__irq对函数的编译没有任何影响,即编译器不会自动保存cpsr及pc的值,也不会添加subs pc, lr, #4和从spsr寄存器恢复cpsr寄存器值的指令,因为cortex m3处理器硬件会自动处理这些问题,无需 软件开发人员关心。