问题描述
我正在使用 Keil ARMCompiler 6.15 (armclang.exe),但我怀疑生成的汇编代码的正确性。 在我看来,属性 'interrupt("IRQ")' 被忽略了。 对我来说,r1 和 r2 也应该保存在堆栈中。 当我删除属性 'used' 时,我的完整功能将被删除(优化)。
谁能看到我犯的错误或我忘记了什么?
最初代码是为 gcc 创建的。
用于中断例程的属性:
#define INTERRUPT_PROCEDURE __attribute__((interrupt("IRQ"),used,section(".IsrSection")))
#define ISR_VARIABLE __attribute__((section(".IsrSection")))
#define FAST_SHARED_DATA __attribute__((section(".FastSharedDataSection")))
C++ 代码:
uint64_t volatile FAST_SHARED_DATA systick_value = uint64_t(0);
extern "C" {
void INTERRUPT_PROCEDURE SysTick_Handler()
{
systick_value++;
}
}
汇编代码:
0x08001280 push {r4,r6,r7,lr}
0x08001282 add r7,sp,#8
0x08001284 mov r4,sp
0x08001286 bfc r4,#0,#3
0x0800128a mov sp,r4
0x0800128c movw r0,#8192 ; 0x2000
0x08001290 movt r0,#8192 ; 0x2000
0x08001294 ldrd r1,r2,[r0]
0x08001298 adds r1,#1
0x0800129a adc.w r2,#0
0x0800129e strd r1,[r0]
0x080012a2 sub.w r4,#8
0x080012a6 mov sp,r4
0x080012a8 pop {r4,pc}
0x080012aa movs r0,r0
0x080012ac movs r0,r0
0x080012ae movs r0,r0
解决方法
您不需要此属性。当堆栈未由硬件对齐到 8 字节(STKALGN 位未设置)并且您将使用具有 64 位参数的函数(如 uint64_t)时,在极少数情况下需要它。当进入 ISR 处理程序时,ARM 会自动将 R0-R3 + 一些其他寄存器保存在堆栈中。如果您使用 FPU,您可能还需要启用 FPU 寄存器堆栈。