为什么中断服务程序 PUSH {r3,r4,r5,lr} 但 POP {r0,r4,r5,lr} 导致 ERROR?

Why the interrupt service routine ,PUSH {r3,r4,r5,lr} but POP {r0,r4,r5,lr},which lead to ERROR?

我正在使用IAR编译例程,但是运行在ARM A7上出错;然后当我打开 IAR 生成的 .lst 文件时,我得到了下面的问题。 是一个ISR,先是push {r3, r4, r5, lr},但是POP {r0, r4, r5, lr}的时候return,R0的值变成了R3的值才push。因此,当从 irqHandler 编辑 return 时,R0 是错误的,这会导致后续例程出错。 为什么 ?

    void irqHandler(void)
    {
         878:   e92d4038    push    {r3, r4, r5, lr}
      volatile u32 *pt = (u32 *)AM_INTC_BASE;
         87c:   e3a044b0    mov r4, #176, 8 ; 0xb0000000
      u32 id_spin;

      id_spin = *(pt+0x200c/4) & 0x3ff;
         880:   e302000c    movw    r0, #8204   ; 0x200c
         884:   e7900004    ldr r0, [r0, r4]
         888:   e1b00b00    lsls    r0, r0, #22
         88c:   e1b00b20    lsrs    r0, r0, #22
         890:   e1b05000    movs    r5, r0
      if(id_spin<32)
         894:   e3550020    cmp r5, #32
         898:   2a000000    bcs 8a0 <irqHandler+0x28>
      {
    #ifdef WHOLECHIPSIM
        print("id_spid<32 error...\r\n",0);
    #endif    
        while(1);
         89c:   eafffffe    b   89c <irqHandler+0x24>
      }
      else
      {
        (pFuncIrq[id_spin-32])();
         8a0:   e59f0010    ldr r0, [pc, #16]   ; 8b8 <.text_8>
         8a4:   e1b01105    lsls    r1, r5, #2
         8a8:   e0910000    adds    r0, r1, r0
         8ac:   e5100080    ldr r0, [r0, #-128] ; 0x80
         8b0:   e12fff30    blx r0
      }
    }
         8b4:   e8bd8031    pop {r0, r4, r5, pc}

没关系,因为R0-R3、R12、LR、PC、xPSR在硬件调用中断向量例程时会自动入栈。当 bxldmpopldrPC 被调用时,硬件执行中断例程退出弹出这些寄存器。

不要检查你的编译器。它知道自己在做什么。检查错误逻辑 - 特别是在中断处理程序中打印字符串。

abi 需要一个 64 位对齐的堆栈,因此 r3 的压入简单地促进了这一点。可以选择任何尚未指定的寄存器。同样,在 pop 上,他们需要清理堆栈,该函数的原型为 void,因此无需关心 return (r0) 并且预计不会保留 r0-r3,因此没有理由在每个上匹配 r3两端也不匹配 r0。

如果他们在推送时选择了编号高于 r3(例如 r6)的寄存器,则需要在弹出时匹配该寄存器。否则 pop 必须是 r0-r3 之一才能不破坏非易失性寄存器。 (无法推送 r3 然后弹出 r6 会破坏 r6)

assemble 关键字 __irq __arm 代码如下:

    __irq __arm void irqHandler(void)
    {
         878:   e24ee004    sub lr, lr, #4
         87c:   e92d503f    push    {r0, r1, r2, r3, r4, r5, ip, lr}
      volatile u32 *pt = (u32 *)AM_INTC_BASE;
         880:   e3a044b0    mov r4, #176, 8 ; 0xb0000000
      u32 id_spin;

      id_spin = *(pt+0x200c/4) & 0x3ff;
         884:   e302000c    movw    r0, #8204   ; 0x200c
         888:   e7900004    ldr r0, [r0, r4]
         88c:   e1b00b00    lsls    r0, r0, #22
         890:   e1b00b20    lsrs    r0, r0, #22
         894:   e1b05000    movs    r5, r0
      if(id_spin<32)
         898:   e3550020    cmp r5, #32
         89c:   2a000000    bcs 8a4 <irqHandler+0x2c>
      {
    #ifdef WHOLECHIPSIM
        print("id_spid<32 error...\r\n",0);
    #endif    
        while(1);
         8a0:   eafffffe    b   8a0 <irqHandler+0x28>
      }
      else
      {
        (pFuncIrq[id_spin-32])();
         8a4:   e59f0010    ldr r0, [pc, #16]   ; 8bc <.text_8>
         8a8:   e1b01105    lsls    r1, r5, #2
         8ac:   e0910000    adds    r0, r1, r0
         8b0:   e5100080    ldr r0, [r0, #-128] ; 0x80
         8b4:   e12fff30    blx r0
      }
    }
         8b8:   e8fd903f    ldm sp!, {r0, r1, r2, r3, r4, r5, ip, pc}^

Cortex A7 PUSH log,它只是压入7个寄存器,所以32位对齐就可以了

关注 link 是日志信息:

http://img.blog.csdn.net/20170819120758443?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcmFpbmJvd2JpcmRzX2Flcw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center