未配置时触发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.sLinkerScript.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中断的主要内容,如果未能解决你的问题,请参考以下文章

如何配置STM32定时器在每次递增/递减时触发中断?

stm32啥触发串口接收中断

STM32:如何配置定时器以在正交编码器模式下每次增量触发中断?

STM32-外部中断,没有硬件干扰就是快乐

STM32F401 外部中断误触发问题

stm32 外部中断打断PWM