前言
在多人协作开发时往往需要用到 Git 来进行版本管理,但是嵌入式开发中有大量的外设初始化配置内容,STM32 开发又往往会搭配 STM32CubeMX 进行,STM32CubeMX 提供了一个图形化界面来管理 STM32 的板上外设,故我们无须关心具体的初始化代码。由此造成了一个问题:这些初始化代码由 STM32CubeMX 生成,常规的项目结构却会导致它们被 Git 追踪(因为 Git 是基于文件来追踪代码的变更的),从而干扰对于项目实际代码的追踪,这对项目管理是非常不友好的。此外,如果有多种 IDE(集成开发环境)可能需要选用不同的工具链,生成的代码结构也是不同的,导致使用不同 IDE 的开发者之间很难协作。
本文旨在寻求一种方案能够将 STM32CubeMX 生成的代码全部排除,开发者可以只关注项目代码的变动。
理论基础
在项目的 .ioc
文件中存有关于板上外设的全部配置内容(实际上 .ioc
文件是 ini 格式的,可以很轻易地被 Git 追踪)。大型项目中往往会启用 FreeRTOS,这意味着我们可以通过一个最高优先级的 Task 来进行初始化,从而不需要对 main.c
做任何修改。各种外设的回调可以通过重写回调函数或注册回调函数来实现,从而也不需要修改任何 Core 中的代码。至于如何让项目构建的时候包含自己的代码,可以通过编译器参数实现。
配置流程
创建项目并完成基本配置
首先使用 STM32CubeMX 创建项目(本文使用 STM32F407VET6 芯片举例,创建项目的过程略),完成基本配置,并在 Middleware and Software Packs
里启用 FreeRTOS,选择 CMSIS_V2。
在 Task and Queues
里新建一个 Task,优先级配置为 osPriorityRealtime7
TIP
CMSIS 是对 FreeRTOS API 的一层封装,使用起来更顺手,CMSIS V2 的 API 可以参考 https://arm-software.github.io/CMSIS_5/RTOS2/html/rtos_api2.html
接下来生成代码,本文将介绍两种环境的配置方法,分别是 CLion + CMake 和 VSCode + EIDE + Makefile。
选择适合的工具链(CLion 用 STM32CubeIDE,EIDE 用 Makefile)并生成代码(GENERATE CODE)
初始化 Git 相关配置
进入项目文件夹,在当前目录开启终端(Windows 11 用户可以在文件夹右键并点击 在此处打开终端
,Linux 用户你肯定知道)
初始化 Git
1 | git init |
TIP
没有 Git 的请上网找一个安装教程(不要使用 baidu 搜索),记得将 Git 加到 PATH
接下来创建一个文件 .gitignore
并复制以下内容
1 | ### STM32CubeMX ### |
用户代码基本结构
1 | UserCode/ |
可以参照以上目录结构来规划项目内容,我们需要创建的是 UserCode/app/app.h
和 UserCode/app/app.c
app.h
1 | /** |
app.c
1 | /** |
Init
函数的名称是创建 Task 时填写的 Entry Funnction
编译器配置
CLion
用 CLion 打开项目后,项目将具有以下目录结构
1 | . |
在 CMakeLists_template.txt
中
1 | add_executable($${PROJECT_NAME}.elf $${SOURCES} $${LINKER_SCRIPT}) |
后添加一行
1 | target_compile_options(${PROJECT_NAME}.elf PRIVATE -include ${CMAKE_SOURCE_DIR}/UserCode/app/app.h) |
并重新生成代码即可
VSCode + EIDE
首先需要完成 EIDE 的基本配置,具体可以参考
记得将 UserCode
加到 IncludeFolders
和 项目资源 里。
配置完成后,目录结构如下
1 | . |
在 Makefile 的
1 | # compile gcc flags |
后面新增
1 | # 非侵入式引入头文件 |
即可
开发流程
初始配置完环境后可以提交为 Init commit
TIP
关于 Git 工作流相关内容可以参考
INFO
本配置流程并没有将 IDE 配置目录 .idea
.vscode
.eide
加到排除目录,旨在统一各成员间的开发环境。如果不需要,也可以将这些目录加到 .gitignore
可以在项目内添加 .clang-format
并启用 Clang
(CLion 需要设置格式化程序为 clang-format,VSCode 需要安装 Clang-Format 插件)进行格式化,统一项目代码格式,以下是我偏好的格式化配置
1 |
|
回调函数被占用的问题
由于我们使用 FreeRTOS 时,往往会将 SysTick 设置为其他的定时器,这种情况下 STM32CubeMX 会在 main.c
中生成 HAL_TIM_PeriodElapsedCallback
回调函数来处理 SysTick,导致回调函数被占用。
此时我们可以在 STM32CubeMX -> Project Manager
-> Advanced Settings
右侧的 Register Callback
中将我们使用的外设打开
自己写一个回调函数
1 | void TIM6_Callback(TIM_HandleTypeDef* htim) |
然后使用
1 | HAL_TIM_RegisterCallback(&htim6, HAL_TIM_PERIOD_ELAPSED_CB_ID, TIM6_Callback); |
函数来注册回调函数,其余外设也有对应的回调注册函数(格式为 HAL_xxx_RegisterCallback
)
IMPORTANT
回调注册一定要在初始化之后,中断开启前进行,否则回调不会被触发