STM32在未配置时,WWDG中断会触发。

23
我有一个应用程序,我正在将其从Keil IDE移植到使用GNU工具链进行构建,因为存在许可问题。我已经成功地设置、构建、烧录并在设备上运行该应用程序。
GNU端的应用程序由于某种原因在弱链接的WWDG中断处理程序中陷入了无限循环。该应用程序不启用WWDG,并且在复位时默认禁用它。我还验证了配置寄存器处于其默认启动值。
除了编译器之外,唯一的区别是链接器和启动文件。然而,两个工具链使用的启动文件和链接器文件都是由STM生成的默认文件。
有任何想法是什么导致这个问题?我已经快要束手无策了。
使用stm32f103XX,请告诉我是否需要其他信息。
编辑: 根据下面的评论,我能够确定实际上是触发了HardFault_Handler。 如果可能有帮助,我在下面包含了回溯输出。
GDB BT:
0 HardFault_Handler ()
1(信号处理程序被调用)
2 0x720a3de in ?? ()

3 0x80005534 在 foo() 中

回溯停止:前一帧与此帧相同(堆栈损坏?)

有两个问题引起了我的注意,虽然我不是 gdb 专家。1)foo 不是一个函数,它是一个常量字符数组;2)0x0720a3de 不是一个有效的内存地址,闪存地址范围从 0x08000000 开始。


2
你确定那真的是WWDG吗?另一个while(1);可能由于优化而共享了该代码。地图文件是否仅显示该地址处的WWDG? - D Krueger
2
你可能有所发现。在.elf文件中,所有默认的irq符号都指向同一个地址,这意味着WWDG_IRQ名称在调试器中使用只是巧合。我将为irq添加强链接函数,以便我可以找出具体的问题所在。 - gettingSmarter
我也卡在了HardFault_Handler,我花了整整一天一夜来找出原因,结果发现我忘记编译所有外设文件(stm32f10x_adc.ostm32f10x_bkp.ostm32f10x_can.ostm32f10x_cec.o... misc.o)并将它们链接起来,感觉自己像个傻瓜‍♂️。 - Kyung Lee
8个回答

14

多亏了D Krueger的推动,我才能够找出实际被调用的HardFault_Handler。所以,任何遇到这个问题的人,请编写临时函数来验证哪个IRQ被真正调用,例如HardFault。造成IRQ调用的真正问题是memcpy导致的错误内存访问,下一步我将解决这个问题。


我非常确定你会发现,不良的内存访问并不是“由memcpy引起的”,而是你对memcpy的调用。 - Clifford
3
最终罪魁祸首竟然是我与编译时正确的选项没有链接。我忘记了链接 -mthumb 和 -mcpu=cortex-m3 这两个选项,因此我正在使用错误的 C 库进行链接。 - gettingSmarter
你会在“临时函数”中放置什么来知道哪一个被调用了?通过GPIO点亮LED?断点? - Matthieu

8
我在将STM32F3 Discovery板的示例代码移植到CooCox CoIDE 1.7.7上,并使用STM32Cube F3库(v1.1.0)进行编译时,遇到了与OP完全相同的错误(表面上是WWDG中断,但实际上是HardFault_Handler触发)。只要我不尝试使用任何中断,代码就能正常运行,但一旦打开SysTick定时器中断,就会触发HardFault异常。
问题在于我忽略了在项目中包含stm32f3xx_it.h和stm32f3xx_it.c文件。它们的缺失并没有引起任何编译器警告/错误。一旦它们被编译和链接进来,带有中断的代码就可以正常运行。

当我尝试将cmake可执行目标分解为库和仅包含main.cpp的可执行文件时,我也遇到了这种情况。结果发现,“stm32l4xx_it.c”实际上是主要可执行文件的一部分,而不足以作为其链接库的一部分。 - CivFan

7
由于与awilhite相同的根本原因,我遇到了这个问题。我正在使用Atollic TrueStudio 8.0.0。我使用它启动了一个针对STM32F030的项目,并(可能手动)添加了具有stm32f0xx.h的库文件夹,该文件定义了ADC1_IRQn(在NVIC设置中使用的IRQ通道号)。
我在main.c中实现了ADC1_IRQHandler(void)(因为我习惯于这样做,并且迄今为止一直有效--x_IRQn-> x_IRQHandler),但是经过2天的挫败后,我发现我的项目中的startup_stm32f0xx.s定义了ADC1_COMP_IRQHandler。
因此,我的ADC中断处理程序未定义,当ADC生成中断时,程序崩溃(WWDG中断)。
希望这能帮助像我这样认为已实现其处理程序但实际上并没有的人。

多亏了你,我只有一天的挫败感 :)startup_xxx.s 定义了中断向量所期望的函数名。从一个项目盲目地复制粘贴源代码到另一个项目时,很容易忽略它,当原始代码使用 ADC1_IRQHandler() 但 STM32 实际上调用的是 ADC1_COMP_IRQHandler() - Matthieu

5

当我合并两个由STM32CubeMX为STM32F2XX处理器分别生成的项目时,遇到了非常相似的问题。一个项目使用以太网外设,而另一个项目则没有。除此之外,这两个项目使用相同的外设集。

通过手动复制文件将两个项目集成在一起后,应用程序在启动第一个任务(启用中断时)后会进入WWDG_IRQHandler。我首先确认WWDG寄存器的WDGA位确实没有设置,因此WWDG外设被禁用。接下来,我验证了中断向量表的初始化是否正确。最终,在挖掘了几个小时后,我意识到我没有在stm32f2xx_it.c中定义ETH_IRQHandler函数,这导致以太网中断被默认处理程序处理,将自己遮蔽为WWDG_IRQHandler -- 可能是由于优化造成的。


3
核心问题是调用了默认处理程序而不是另一个IRQ处理程序。我怀疑我们的情况不同,但这是我的解决方案:
我正在开发一个C++项目,也遇到了相同的问题。这是我第一次从头开始使用CMSIS制作项目。经过多次不成功的尝试后,当我检查生成的项目时,我注意到在stm32xxxx_it.h中的IRQ处理程序函数原型受到了以下保护:
extern "C"
{
    void TIM7_IRQHandler(void);
}

有了这些保护措施,链接器可以找到我的中断处理程序函数。

只是我遇到的确切问题。 - Hamza Hajeir
我正在使用PlatformIO,我不得不手动将stm32f1xx_it.c更改为stm32f1xx_it.cpp。我不知道为什么头文件没有捕获__cplusplus定义,并且为什么它是使用C编译器编译的。这可能是一个PlatformIO问题,或者是我的理解不够...也许。 - Hamza Hajeir

2
我稍微详细地解释一下我是如何到达这里的,以及我如何使用来自@Mike的见解进行更正。
我在Eclipse SW4STM32的演示项目中运行了一个项目,但由于源文件和头文件散布在各个地方,因此我希望有一个更“紧凑”的项目,更容易定制并用作较小修改的基础(在Git中更易于跟踪)。
我创建了一个空的AC6项目,指向同一块板子。它生成了HAL驱动程序、startup_stm32.sLinkerScript.ld。然后我将所有.c和相应的.h从原始项目复制到我的新项目中(这本身就很麻烦,因为它们分散在BSP、CMSIS、Components、Middlewares等目录中)。一切都编译并似乎工作正常,直到我开始做一些修改。
在调试器中,似乎所有函数调用都有效,直到我进入Default_Handler,该函数定义在startup_stm32.s中,在while(1)主循环中出现,看起来是从WWDG_IRQHandler中出现的。实际上,那是默认的IRQ处理程序,用于非用户定义的处理程序(WWDG_IRQHandler是第一个声明的处理程序,由gdb报告,如@D Krüger所示)。
我开始查看编译器和链接器选项或链接器脚本,但没有什么运气,直到我意识到唯一没有检查的文件是startup_stm32.s,它确实不同。
我盲目地复制粘贴它,就完成了!
我可以给出的解释是,当中断发生时,STM32调用在startup_stm32.s中定义的IRQ处理程序,最初所有处理程序都指向Default_Handler()(稍后被链接器覆盖)。因此,如果您复制的.c文件定义了一个具有稍微不同名称的处理程序(但与其自己的startup_xxx.s一致),则会调用Default_Handler()(这是一个无限循环),而不是您定义的处理程序。事情就会出错。
有关更多信息,请参见https://www.freertos.org/Debugging-Hard-Faults-On-Cortex-M-Microcontrollers.html
注:我不喜欢盲目地复制粘贴而不完全理解,但时间限制和里程碑通常会把你推向你不愿意探索的领域......

0

补充一下我的看法。我在stm32h7上遇到了这个问题,但是对我来说原因是cube“忘记”在使用TIM16作为时间基准源时添加TIM16_IRQHandler。一开始并没有发生这种情况,但在多次代码重新生成后出现了这种情况。似乎是cube的一个bug,因为TIM16仍然被设置,但是中断处理程序被删除了。所以切换到TIM17然后再切换回来可以解决这个问题。


0
在我的情况下,我有一个函数是用GCC汇编语言编写的,这个函数从ARM汇编语言中迁移而来。在汇编文件中添加了.thumb_func行之后,问题就消失了。
我曾经遇到过这个错误:
(gdb) c
+c
Continuing.

Program received signal SIGINT, Interrupt.
WWDG_IRQHandler () at ...startup_stm32f40_41xxx.s:121

(gdb) bt
#0  WWDG_IRQHandler () at ...startup_stm32f40_41xxx.s:12
#1  <signal handler called>
#2  RTOS_SysTick_Handler () at ...osKernel.s:18
#3  <signal handler called>
#4  0x0800021a in task0 () at ...main.cpp:10
#5  0x08000214 in frame_dummy ()
#6  0x00000000 in ?? ()

RTOS_SysTick_Handler是一个用汇编语言编写的函数,而WWDG_IRQHandler总是在该函数中的任何第一条汇编指令之前被触发(尝试了不同的指令,但没有改变任何东西)。

我对C代码进行了一些调整,在某个时候,我遇到了另一个处理程序:UsageFault,这导致我看到了.thumb_func提示:ARM Cortex M4 SVC_Handler "UsageFault"


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接