Keil5 工程迁移到 STM32IDE,包含C/C++,FreeRTOS
Keil5 工程迁移到 STM32CubeIDE 的一次整理:C 工程、C++ 工程和 FreeRTOS 注意点
最近把一个原本在 Keil5 里维护的 STM32 工程迁移到了 STM32CubeIDE。然后在网上没找到使用CubeMX生成,并且包含c++的工程的迁移教程。因此研究完后写了这篇文章,给遇到同类问题的朋友做个参考。
迁移过程本身不算复杂,但有几个地方比较容易踩坑:CubeMX 生成工程时的 Toolchain 选择、CubeIDE 的 Source Location、C++ 文件不会自动加入编译、FreeRTOS 的 port 文件也要换成 GCC 版本。
适用场景
本文主要适用于下面几类情况:
-
原工程使用 Keil5 编译,现在想迁移到 STM32CubeIDE。
-
工程由 STM32CubeMX 生成,包含
.ioc文件。 -
工程可能是纯 C 工程,也可能混合了 C/C++ 文件。
-
工程可能使用 FreeRTOS。
目录
五、为什么 Keil 能编译 C++,IDE 导入后却按 C 工程处理
一、纯 C 工程迁移
1. 在 CubeMX 中切换 Toolchain
先打开工程对应的 .ioc 文件,在 STM32CubeMX 中把工程的 Toolchain / IDE 改为 STM32CubeIDE。

这里建议勾选生成工程相关选项,然后重新生成代码。

2. 在 STM32CubeIDE 中导入工程
打开 STM32CubeIDE,导入工程根目录。

导入完成后,可以在工程属性里的 C/C++ Build 页面检查构建配置是否正常生成。

如果这里能看到 Debug / Release 之类的构建配置,说明 CubeIDE 已经识别到了工程的构建信息。
3. 添加头文件路径
打开工程的 Properties,在编译器设置里补齐 include path。

常见需要确认的目录包括:
-
Core/Inc -
Drivers/STM32F1xx_HAL_Driver/Inc -
Drivers/CMSIS/Device/ST/STM32F1xx/Include -
Drivers/CMSIS/Include -
项目中自己新增的模块头文件目录
具体路径要根据自己的芯片型号和工程目录调整。
4. 添加宏定义
Keil 工程中原本配置的宏定义,也需要同步到 CubeIDE 中。

常见宏包括:
USE_HAL_DRIVER STM32F103xB
这里的芯片宏一定要和实际芯片型号匹配。例如 STM32F103C8T6 一般使用 STM32F103xB,不要直接照抄其他工程。
5. 配置 Source Location
这一步要看实际情况。如果工程已经可以正常编译,就不需要额外调整。
如果编译时出现一堆来自 CMSIS 示例、RTOS、NN、Template 等目录的错误,多半是 Source Location 把过大的目录加进来了,导致 CubeIDE 把不该参与编译的文件也编译了。

处理思路有两个。
第一种方式是只加入真正需要编译的源码目录,例如:
Drivers/STM32F1xx_HAL_Driver/Src

然后按需添加工程自己的源码目录。

第二种方式是保留当前目录结构,但把不需要编译的文件手动排除。

在文件属性中勾选 Exclude from build。

我个人更推荐第一种方式:只把必要目录加入构建。这样工程结构更清楚,后续也不容易莫名其妙编译到示例文件。
6. 设置优化等级
CubeIDE 使用 GCC 工具链,优化等级也可以在工程属性中配置。

几个常见选项的含义:
| 优化等级 | 含义 |
|---|---|
-O0 |
不优化,最适合初期调试 |
-Og |
为调试体验做优化,推荐调试阶段使用 |
-O1 |
轻度优化 |
-O2 |
常用性能优化,发布版本比较常见 |
-O3 |
更激进的速度优化,可能增大代码体积 |
-Os |
优先优化代码体积 |
-Ofast |
非常激进的速度优化,会放宽部分标准规则 |
-Oz |
更极限地压缩代码体积 |
调试阶段建议先用 -O0 或 -Og,否则断点、变量观察、单步执行都可能变得不直观。
7.编译工程

二、带 FreeRTOS 工程的注意点
如果工程使用了 FreeRTOS,要特别注意 portable 目录下的 port 文件。
Keil 工程常用的是 RVDS 路径:
Middlewares\Third_Party\FreeRTOS\Source\portable\RVDS\ARM_CM3\port.c
迁移到 STM32CubeIDE 后,因为编译链变成了 GCC,所以应该改成 GCC 对应路径:
Middlewares\Third_Party\FreeRTOS\Source\portable\GCC\ARM_CM3\port.c
对比起来就是:
- Middlewares\Third_Party\FreeRTOS\Source\portable\RVDS\ARM_CM3\port.c + Middlewares\Third_Party\FreeRTOS\Source\portable\GCC\ARM_CM3\port.c

原因也很好理解:FreeRTOS 本身是通用的,但任务切换、开关中断、进入临界区、触发 PendSV、处理 SVC/SysTick 这些底层动作,都依赖具体 CPU 架构和编译器汇编语法。
所以 FreeRTOS 会把这些平台相关代码放在 portable 目录中。Keil 对应 RVDS,STM32CubeIDE 对应 GCC,迁移时这里不能混用。
三、编译结果中的 text、data、bss 怎么看
CubeIDE 编译后经常会看到类似下面的结果:
text 48216 data 596 bss 12772 dec 61584 hex f090
这些字段可以这样理解:
| 字段 | 含义 |
|---|---|
text |
代码段和只读常量,主要占用 Flash |
data |
已初始化的全局变量或静态变量,初值存放在 Flash,运行时占用 RAM |
bss |
未初始化或初始化为 0 的全局变量或静态变量,只占用 RAM |
dec |
十进制总和,通常是 text + data + bss |
hex |
dec 的十六进制表示 |
需要注意的是,dec 只是一个总和,不等同于真实 Flash 或 RAM 占用。更实用的判断方式是:
Flash 占用约等于 text + data RAM 占用约等于 data + bss
四、C/C++ 混合工程迁移
如果项目里除了 C 文件,还有 C++ 文件,迁移时要多处理一步。
1. 在 CubeMX 中切换 Toolchain
这一步和纯 C 工程一样,先在 CubeMX 中把 Toolchain / IDE 改成 STM32CubeIDE,然后重新生成工程。


2. 在 CubeIDE 中新建或导入 IOC 工程
在 STM32CubeIDE 中新建 .ioc 工程。

3. 手动导入 C++ 文件
这里是 C/C++ 混合工程最容易忽略的点:CubeIDE 新建工程时通常只会自动加入 C 文件,.cpp 文件需要手动导入或手动加入工程,才会参与编译。

导入后,在工程属性里应该能看到 C++ 编译器相关配置。

4. 添加 C++ 工程的头文件路径
C++ 工程同样需要补齐 include path。

后续步骤和纯 C 工程一致:从1.4开始添加宏定义、检查 Source Location、处理 FreeRTOS port 文件、设置优化等级。
五、为什么 Keil 能编译 C++,IDE 导入后却按 C 工程处理
这个问题本质上是 Keil 和 STM32CubeIDE 对工程类型的判断机制不一样。
Keil 的工程文件是 .uvprojx。它会保存 C/C++ 编译设置,而且 Keil 对 .cpp 文件会自动使用 C++ 模式编译。
STM32CubeIDE 基于 Eclipse CDT,它主要读取自己的工程文件,例如:
.project .cproject .mxproject
如果这些文件里没有 C++ nature 或 G++ toolchain 配置,CubeIDE 不会因为目录里存在 .cpp 文件,就自动把整个工程转换成 C++ 工程。
几个文件的大致作用如下:
| 文件 | 作用 |
|---|---|
.project |
描述 Eclipse 工程类型,包括工程名、builder、nature 等 |
.cproject |
CDT 构建配置,包括 Debug / Release、gcc / g++、编译器、链接器、include paths、宏定义、优化等级、链接脚本、排除规则等 |
.mxproject |
CubeMX 生成代码时的工程结构和文件清单,包括源文件、头文件、库文件和路径信息 |
所以 C++ 工程迁移时,不能只把 .cpp 文件放进目录里,还要确保 CubeIDE 工程本身具备 C++ 构建配置。
六、迁移检查清单
最后整理一个检查清单,迁移时可以按这个顺序过一遍:
-
CubeMX 的 Toolchain / IDE 是否已经切换为 STM32CubeIDE。
-
是否重新生成了工程文件。
-
CubeIDE 中是否能看到正常的
C/C++ Build配置。 -
include path 是否补齐。
-
Keil 中原有的宏定义是否同步到 CubeIDE。
-
Source Location 是否只包含需要编译的源码目录。
-
不需要编译的示例文件、Template 文件是否已排除。
-
使用 FreeRTOS 时,是否切换到了
portable/GCC下的 port 文件。 -
C++ 文件是否已经手动加入工程并参与编译。
-
C++ 工程是否能看到 G++ / C++ Compiler 相关配置。
-
优化等级是否适合当前阶段,调试阶段优先考虑
-O0或-Og。 -
编译后的 Flash / RAM 占用是否合理。
总结
Keil5 迁移到 STM32CubeIDE,核心不是“把代码复制过去”这么简单,而是要把原来 Keil 工程里的构建信息迁移完整,包括头文件路径、宏定义、源码目录、编译器类型、FreeRTOS port 文件和优化等级。
纯 C 工程一般比较顺,主要注意 Source Location 不要误编译无关文件。C/C++ 混合工程则要额外关注 .cpp 文件是否真正加入了 CubeIDE 的 C++ 构建系统。
这次整理下来,最大的经验是:迁移后先别急着改业务代码,先把构建系统理顺。只要编译链、路径和宏定义对齐,后面的错误定位会轻松很多。
更多推荐


所有评论(0)