如何禁止TI ARM Clang在嵌套中断ISR中使用R14(LR)作为临时寄存器?
针对ARM R5F嵌套IRQ场景下TI Clang使用LR的问题解决方案
1. 编译层面禁止编译器使用LR
全局编译选项
添加 -ffixed-r14 到编译命令行,强制编译器将R14(LR)视为固定寄存器,不会在任何函数中用作临时变量。该方案适合所有ISR都需要保护LR的场景,但会影响整个编译单元的寄存器分配策略。
函数级属性控制
如果仅需针对特定ISR保护LR,使用 preserve_registers 属性配合中断属性修饰ISR:
void low_priority_isr(void) __attribute__((interrupt("IRQ"), preserve_registers("r14"))) { __enable_irq(); // 重新使能中断支持嵌套 // ISR业务逻辑 }
这个属性会让编译器在该函数中跳过使用R14,避免覆盖中断返回地址。
2. 手动保存LR到volatile变量
若编译选项/属性无法满足需求,可在ISR开头通过内嵌汇编将LR保存到volatile变量,防止编译器优化或改写:
static volatile uint32_t lr_saved; void low_priority_isr(void) __attribute__((interrupt("IRQ"))) { // 保存当前LR到变量 asm volatile("mov %0, lr" : "=r"(lr_saved) : : ); __enable_irq(); // ISR核心处理代码 // 恢复LR(中断返回前执行) asm volatile("mov lr, %0" : : "r"(lr_saved) : ); }
volatile修饰确保保存操作不会被编译器优化,内嵌汇编直接操作寄存器,绕过编译器的寄存器分配逻辑。
关键提示
- 务必为ISR添加
__attribute__((interrupt("IRQ")))属性,该属性会让编译器生成符合ARM R5F中断返回规范的代码,正确处理模式切换与寄存器恢复。 - ARM R5F的IRQ模式下,嵌套中断会直接覆盖LR_irq,因此必须在重新使能中断前完成LR的保存操作。
内容的提问来源于stack exchange,提问作者user4574
相关产品推荐
相关产品推荐

