为什么在为 Cortex-M 中断处理程序生成的程序集中存在死循环?

Why there is a dead loop in the generated assembly for a Cortex-M interrupt handler?

我正在使用 MDK uVision IDE 学习 Cortex-M。我写了一个简单的 SysTick_Handler() 来替换 WEAK 默认 SysTick_Handler() 这是一个简单的死循环。

我的SysTick_Handler():

反汇编:

我对突出显示的流水线感到困惑。这简直就是死循环。

它为什么在那里?为什么尽管我已经用自己的 SysTick_Handler 覆盖了 WEAK 默认实现,但工具链仍然生成它?

我仍然可以在该行放置一个断点并且它可以命中。在那种情况下,我的代码将永远不会被执行。

但奇怪的是,如果我去掉那一行的断点,我的代码就可以执行了。这怎么可能?

(感谢社区提供的所有提示。我想我现在可以解释了。)

死循环是我的 main() 函数的一部分,如下所示。 main() 函数就在同一个 C 文件中我的 SysTick_Handler 之上。

int main (void)
{
    LED_Initialize();
    SysTick->VAL = 0x9000;                                                                                   
    //Start value for the sys Tick counter
    SysTick->LOAD = 0x9000;                                                                                  
    //Reload value 
    SysTick->CTRL = SYSTICK_INTERRUPT_ENABLE|SYSTICK_COUNT_ENABLE;  //Start and enable interrupt
    while(1)
    {
        ;  // <========= This is the dead loop I saw!
    }
}

为了双重确认,我将 while 循环修改为以下内容:

int main (void)
{
    volatile int32_t jj = 0;
    LED_Initialize();
    SysTick->VAL = 0x9000;                                                                                  //Start value for the sys Tick counter
    SysTick->LOAD = 0x9000;                                                                                 //Reload value 
    SysTick->CTRL = SYSTICK_INTERRUPT_ENABLE|SYSTICK_COUNT_ENABLE;  //Start and enable interrupt
    while(1)
    {
        ;
        jj+=0x12345; // <====== add some landmark value
    }
}

现在生成的代码是这样的:

虽然还是放在了SysTick_Handler下面。我在那里放置一个断点来检查到底发生了什么:

R1是常量0x12345R0 是局部变量 jj。我们可以看到 R1 确实包含地标值 0x12345,它被添加到 R0 (jj)。所以它一定是 main().

中我的 while(1) 循环的一部分

所以,反汇编是正确的。只是调试器未能在源代码和反汇编之间提供正确的交错。

顺便说一句,记得在修改代码后重建目标,否则 uVision IDE 调试器将不会反映最新的更改....