Realview MDK中编译器对中断处理的过程详解


Realview MDK 中编译器对中断处理的过程详解

在 ARM 程序的开发过程中,对中断的处理是非常普遍且重要的。Realview MDK 使用的 RVCT 编译器提供了 __irq 关键字,使用此关键字修饰的函数被编译为中断处理函数。在编译过程中,编译器会自动添加中断处理过程中现场保护和恢复的代码,减小程序的开发难度,加快软件的开发过程。

ARM 核对异常的处理过程

在理解 __irq 关键字的作用之前,先看一下 ARM 核对异常的处理过程。当产生异常时,ARM 核会执行以下步骤:

  1. 拷贝 CPSR 寄存器的内容到 SPSR_ 寄存器中。
  2. 设置适当的 CPSR 位,改变处理器状态进入 ARM 态和处理器模式,从而进入相应的异常模式。
  3. 在需要的情况下,设置中断禁止位,禁止相应中断。
  4. 保存返回地址到 LR_,同时设置 PC 为相应的异常向量。

异常返回时,处理器需要从 SPSR_ 寄存器中恢复 CPSR 的值,同时从 LR_ 恢复 PC。具体的异常返回指令如下:

  • 从 SWI 和 Undef 异常返回时使用:

    movs pc, LR;
    
  • 从 FIQ、IRQ 和预取终止返回时使用:

    SUBS PC, LR, #4;
    
  • 从数据异常返回时使用:

    SUBS PC, LR, #8;
    

在使用上述指令异常返回时,如果 LR 之前被压栈,可以使用以下指令:

LDMFD SP!, {PC};

Realview MDK 中 __irq 关键字的作用

理解了 ARM 异常处理的过程后,Realview MDK 中 __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 处理器硬件会自动处理这些问题,无需软件开发人员关心。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

2401_87496566

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值