为什么在为 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
是常量0x12345
。 R0
是局部变量 jj
。我们可以看到 R1
确实包含地标值 0x12345
,它被添加到 R0
(jj
)。所以它一定是 main()
.
中我的 while(1)
循环的一部分
所以,反汇编是正确的。只是调试器未能在源代码和反汇编之间提供正确的交错。
顺便说一句,记得在修改代码后重建目标,否则 uVision IDE 调试器将不会反映最新的更改....
我正在使用 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
是常量0x12345
。 R0
是局部变量 jj
。我们可以看到 R1
确实包含地标值 0x12345
,它被添加到 R0
(jj
)。所以它一定是 main()
.
while(1)
循环的一部分
所以,反汇编是正确的。只是调试器未能在源代码和反汇编之间提供正确的交错。
顺便说一句,记得在修改代码后重建目标,否则 uVision IDE 调试器将不会反映最新的更改....