首页 > 解决方案 > 使用 CMake 构建 STM32 固件时的中断处理

问题描述

我调试用 CMake 创建的 STM32 项目。它使用 HAL 库,一开始我配置了 HAL 和 SysTick。

root/
├─ core/
│  ├─ core.c
│  ├─ core.h
│  ├─ stm32g4xx_it.c
│  ├─ stm32g4xx_it.h
│  ├─ CMakeLists
├─ main.c
├─ startup.s
├─ CMakeLists.txt

startup.s文件包含弱SysTick_Handler,如下:

.weak   SysTick_Handler
.thumb_set SysTick_Handler,Default_Handler

stm32g4xx_it.c还包含SysTick_Handler覆盖弱声明的内容。问题是当编译、链接和加载应用程序时,如上所示,SysTick 中断以Default_Handler. 如果我从文件中删除弱声明startup.s,那么它可以正常工作并执行正确的处理函数。我认为这是 cmake 工作方式的结果。在根目录中有一个主 CMakeLists.txt 文件,它编译startup.smain.c文件,然后链接核心库。正确SysTick handler的是放在核心库中,因此startup.s文件的编译“看不到”这个处理函数的其他实现。解决它的正确而优雅的方法是什么?

我想到的另一个问题是我应该如何为其他中断处理程序编写代码以及如何在 CMake 构建系统中链接它们?假设我有一个 UART 模块,并且该模块有自己的中断处理程序。我应该创建一个基于startup.s文件的单独库并将所有其他具有中断处理程序的模块链接到它吗?我认为 CMake 应该让构建更透明、更易读和更容易,但这样看起来更像意大利面条。可能我错过了一些东西......


编辑 2021 年 4 月 14 日

我发现问题仅与启动 asm 文件有关。例如,我可以在main.c中创建一个弱函数符号,例如:

__attribute__((weak)) void SystemInit(void)

在核心库中,在core.c我创建函数:

void SystemInit(void)

然后在编译并链接core.c中的正确函数后使用。所以看起来这里有一些与 asm 文件严格相关的东西。

标签: assemblycmakestm32interrupt-handlingstartupscript

解决方案


这种链接器行为的原因是它以不同的方式处理库。当它在源文件中找到弱符号时,它会停止在库中查找相同的符号。原因是库提供了一些功能,开发人员应该能够覆盖这些功能以使它们与自己的项目保持一致。

无需在微控制器的嵌入式项目中使用库。我发现它会引起更多的痛苦。一些开发人员不在add_library()他们的CMakeLists.txt. 在使用 CMake 时,我觉得它不是很合理。它用于更好地组织项目文件和管理模块之间的依赖关系。

这里的问题可以通过使用OBJECT库简单地解决。该类型的链接已添加到target_link_libraries3.12 版本中。我认为它是专门为微控制器项目添加的,而且效果非常好。


推荐阅读