未配置时触发STM32 WWDG中断
Posted
技术标签:
【中文标题】未配置时触发STM32 WWDG中断【英文标题】:STM32 WWDG interrupt firing when not configured 【发布时间】:2015-02-21 19:17:01 【问题描述】:由于许可证问题,我有一个从 Keil IDE 移植以使用 GNU 工具链构建的应用程序。我已经成功地在设备上设置、构建、刷写和运行应用程序。
GNU 端的应用程序由于某种原因卡在 WWDG 的弱链接 IRQ 处理程序中,这是一个无限循环。该应用程序不启用 WWDG,默认情况下在重置时禁用。我还验证了配置寄存器的默认启动值。
除了编译器之外,唯一的区别是链接器和启动文件。但是,两个工具链使用的启动文件和链接器文件都是 STM 生成的默认文件。
知道是什么原因造成的吗?我快到这里了。
使用 stm32f103XX,如果有任何其他信息会有所帮助,请告诉我。
编辑: 使用下面的 cmets,我能够确定它实际上是被触发的 HardFault_Handler。 如果可能有帮助,我已经包含了下面的回溯输出
GDB BT:
0 HardFault_Handler ()
1(调用的信号处理程序)
2 0x720a3de 在?? ()
3 0x80005534 in foo()
回溯停止:前一帧与此帧相同(损坏的堆栈?)
虽然我不是 gdb 专家,但我觉得有两件事很突出。 1) foo 不是一个函数,它是一个 const 字符数组 2) 0x0720a3de 不是一个有效的内存地址,闪存地址范围从 0x08000000 开始
【问题讨论】:
你确定这真的是 WWDG 吗?由于优化,另一个while(1);
可能正在共享该代码。地图文件是否仅显示该地址的 WWDG?
您可能正在做某事。似乎在 .elf 文件中,所有默认的 irq 符号都指向相同的地址,我想这意味着 WWDG_IRQ 名称在调试器中使用只是巧合。我将为 irq 添加强链接函数,这样我就可以找出究竟是哪一个是罪魁祸首。
我也卡在HardFault_Handler
里了,找了半天半夜搞清楚原因,结果忘记编译所有外围文件了(stm32f10x_adc.o
,stm32f10x_bkp.o
,stm32f10x_can.o
,stm32f10x_cec.o
...misc.o
) 并链接它们,我觉得我是个傻瓜????????♂️
【参考方案1】:
多亏了 D Krueger 的裤子。我能够弄清楚 HardFault_Handler 是实际被调用的。所以,任何偶然发现这篇文章的人,通过编写临时函数来验证真正调用了哪个 IRQ 来掩盖可能的罪魁祸首,即 HardFault。 IRQ 调用的真正问题是 memcpy 对内存的访问不正确,我正在着手解决这个问题。
【讨论】:
我很确定你会发现错误的内存访问不是“by memcpy”,而是your call to memcpy。 最后的罪魁祸首是我未能链接到我正在编译的正确选项。我忘记链接 -mthumb 和 -mcpu=cortex-m3 选项。所以我链接了不正确的 c 库。 你在“临时函数”里放了什么才知道调用的是哪一个?通过GPIO点亮LED?断点?【参考方案2】:在移植 STM32F3 Discovery 板的示例以使用 STM32Cube F3 库 (v1.1.0) 在 CooCox CoIDE 1.7.7 中编译时,我遇到了与 OP 完全相同的错误(明显的 WWDG 中断,但实际上是 HardFault_Handler 触发)。只要我不尝试使用任何中断,代码就可以正常运行,但只要我打开 SysTick 定时器中断,就会触发 HardFault 异常。
问题是我忽略了在项目中包含 stm32f3xx_it.h 和 stm32f3xx_it.c 文件。他们的缺席并没有导致任何编译器警告/错误。一旦它们被编译并链接进去,带有中断的代码就可以正常运行了。
【讨论】:
【参考方案3】:由于与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()
时。【参考方案4】:
在合并由 STM32CubeMX 为 STM32F2XX 处理器单独生成的两个项目时,我遇到了一个非常相似的问题。一个项目正在使用以太网外围设备,而另一个则没有。除了这一点不同,这两个项目使用了相同的外设。
通过手动复制文件将两个项目集成在一起后,应用程序将在启动第一个任务后(第一次启用中断时)进入 WWDG_IRQHandler。我首先确认 WWDG 寄存器的 WDGA 位确实没有设置,因此,WWDG 外设被禁用。接下来,我验证了中断向量表已正确初始化。最后,经过几个小时的挖掘,我意识到我没有在 stm32f2xx_it.c 中定义 ETH_IRQHandler 函数,这引发了由默认处理程序处理的以太网中断,将自己屏蔽为 WWDG_IRQHandler - 可能是由于优化。
【讨论】:
【参考方案5】:核心问题是调用了默认处理程序而不是另一个 irq 处理程序。我怀疑我们的情况是否相同,但这是我的解决方案:
我正在做一个 c++ 项目,我也遇到了同样的情况。这是我第一次使用 CMSIS 从头开始制作项目。经过一些不成功的尝试后,当我注意到stm32xxxx_it.h
中的 IRQ 处理函数原型被这些保护时,我经历了一个生成的项目:
extern "C"
void TIM7_IRQHandler(void);
有了这些守卫,链接器可以找到我自己的中断处理函数。
【讨论】:
正好是我遇到的问题 我正在使用platformio,我也必须手动将stm32f1xx_it.c
更改为stm32f1xx_it.cpp
。我不知道头文件没有捕获 __cplusplus 定义,以及为什么它是用 C 编译器编译的。这可能是 PlatformIO 问题。或者我缺乏理解......也许。【参考方案6】:
我将详细说明是什么导致我来到这里,以及我如何使用来自 @Mike 的见解来纠正它。
我有一个项目在 Eclipse SW4STM32 中的演示项目上运行良好,但源代码和头文件分散在各处,因此我希望有一个更“紧凑”的项目,更易于定制和用作小修改的基础(并且在 Git 中更容易理解)。
我针对同一块板创建了一个空的 AC6 项目。它生成了 HAL 驱动程序,startup_stm32.s
和 LinkerScript.ld
。然后,我将原始项目中的所有.c
和相应的.h
复制到我的新项目中(这本身就很痛苦,因为它们分散在 BSP、CMSIS、组件、中间件等目录中)。在我开始修改之前,一切都已编译并且似乎可以正常工作。
在调试器中,似乎所有函数调用都在工作,直到while(1)
主循环我最终进入startup_stm32.s
中定义的Default_Handler
,似乎来自WWDG_IRQHandler
。这实际上是非用户定义的处理程序的默认 IRQ 处理程序(WWDG_IRQHandler
是第一个声明的,gdb 报告了它,如 @D Krüger 所示)。
我开始查看编译器和链接器选项或链接器脚本,但运气不佳,直到我意识到我唯一没有检查的文件是 startup_stm32.s
,确实不同。 p>
我盲目地复制粘贴它,瞧!
我可以给出的解释是,当中断发生时,STM32 正在调用 IRQ 处理程序在startup_stm32.s
中定义,所有这些处理程序最初都指向Default_Handler()
(后来被链接器覆盖)。因此,如果您复制的 .c
文件定义了一个名称略有不同的处理程序(但与其自己的 startup_xxx.s
一致),您最终将调用 Default_Handler()
(这是一个无限循环)而不是你定义的一个。事情出了问题。
更多信息请参见https://www.freertos.org/Debugging-Hard-Faults-On-Cortex-M-Microcontrollers.html。
注意我不乐意在没有完全理解的情况下盲目复制粘贴,但时间限制和里程碑通常会将您推向您不乐于探索的领域...
【讨论】:
【参考方案7】:就我而言,我有一个用 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"。
【讨论】:
【参考方案8】:将添加我的 5 美分。我在 stm32h7 上遇到了这个问题,但对我来说,原因是当 TIM16 用作时基源时,多维数据集“忘记”添加 TIM16_IRQHandler。它不是在开始时发生,而是在几次代码重新生成之后发生。看起来像立方体中的一个错误,因为 TIM16 仍然设置,但中断处理程序已被删除。所以切换到 TIM17 并返回解决了这个问题。
【讨论】:
以上是关于未配置时触发STM32 WWDG中断的主要内容,如果未能解决你的问题,请参考以下文章