STM32 开发环境配置(Ubuntu + VSCode + CubeMX + GCC 全流程)
0. 为什么用这套方案?
开发 STM32 有三条主流路线,先帮你选对路:
| | | |
|---|
| | | 收费、强绑 Windows、Linux 只能 Wine |
| | | |
| 👉 CubeMX + VSCode + GCC(本方案) | | 免费、轻量、编辑器现代、Git 友好、可命令行自动化 | |
核心理念:CubeMX 只负责「画外设 + 生成代码骨架」,编译/烧录/调试全部交给开源命令行工具,VSCode 作为统一的编辑与调试前端。
1. 整体工具链一览(你需要装什么)
最终你会拥有下面这张表里的所有工具。逐项对照检查即可:
| | | |
|---|
arm-none-eabi-gcc | | | arm-none-eabi-gcc --version |
libnewlib-arm-none-eabi | | | dpkg -l | grep newlib |
make | | | make --version |
cmake | | | cmake --version |
gdb-multiarch | | | gdb-multiarch --version |
openocd | | | openocd --version |
stlink | | | st-flash --version |
| | | |
| | | |
[!tip] 关于 arm-none-eabi-gdb网上老教程会让你装 arm-none-eabi-gdb。但 Ubuntu apt 的 gcc-arm-none-eabi 包不含 gdb。本方案改用 gdb-multiarch,功能完全等价、更新更全,是 Ubuntu 官方推荐的多架构调试器。配置里把 GDB 路径写成 gdb-multiarch 就行(见第 7 节)。
2. 第一步:安装交叉编译工具链(一行命令)
打开终端,复制粘贴:
sudo apt updatesudo apt install -y \ gcc-arm-none-eabi \ libnewlib-arm-none-eabi \ libstdc++-arm-none-eabi-newlib \ make \ cmake \ gdb-multiarch \ openocd \ stlink-tools \ git
逐条解释这个大命令装了什么:
| |
|---|
gcc-arm-none-eabi | ARM 交叉编译器全家桶(含 gcc/g++/objcopy/size/ar/ld…) |
libnewlib-arm-none-eabi | 针对裸机的 C 标准库(printf/malloc 之类的实现) |
libstdc++-arm-none-eabi-newlib | C++ 标准库支持(写 C++ 才需要,装上不亏) |
make | |
gdb-multiarch | |
openocd | |
stlink-tools | 命令行烧录(st-flash / st-info) |
git | |
[!warning] 重要:OpenOCD 版本与芯片支持apt 装的 openocd 是 0.12.0。如果你用很新的芯片(如 STM32H5 / STM32U5),可能需要从 openocd 官方 编译更新版。本笔记实测 F1/F4 系列,apt 版完全够用。
装完立刻验证:
arm-none-eabi-gcc --version# 应输出 13.2.1make --version# GNU Make 4.3gdb-multiarch --version# GNU gdb 15.xopenocd --version# 0.12.0st-flash --version# v1.8.0
3. 第二步:配置 USB 调试器权限(udev 规则)
不配这步,插上 ST-Link 会报「无权限访问」。装好 stlink-tools 后,规则文件通常已就位,但要确认 + 重载:
# 1. 确认规则文件存在(装 stlink-tools 时自带)ls /lib/udev/rules.d/ | grep stlink# 应看到: 49-stlinkv1.rules 49-stlinkv2.rules 49-stlinkv2-1.rules 49-stlinkv3.rules# 2. 如果用的是 ARM 官方/SEGGER 调试器,补一条 ST 官方规则(可选)# 下载: https://wiki.st.com/stm32mcu/wiki/Getting_started_with_STM32CubeIDE#USB_driver_installation# 拷到 /etc/udev/rules.d/ 后执行下面的重载命令# 3. 重载规则 + 触发sudo udevadm control --reload-rulessudo udevadm trigger
插上开发板后验证设备是否被识别:
lsusb | grep -i stlink# 看到 ST-Link 设备ls /dev/stlink* 2>/dev/null# 可能有 st-link 设备节点st-info --probe# 应列出连接的 ST-Link 和目标芯片
[!note] 拔插后仍无权限?把当前用户加入 plugdev/dialout 组(Ubuntu 24.04 通常默认已加):
sudo usermod -aG plugdev,dialout $USER
然后注销重新登录才生效。
4. 第三步:安装 STM32CubeMX
CubeMX 是 ST 官方的图形化配置工具,基于 Java,但安装包自带 JRE,无需单独装 Java。
安装步骤
- 下载:访问官网 https://www.st.com/en/development-tools/stm32cubemx.html,需要注册/登录 ST 账号,下载 Linux 版(
en.STM32CubeMX_v6.xx.linux.zip 或直接 STM32CubeMX 安装程序 .sh)。 - 解压并运行安装程序:
bash cd ~/Downloads unzip en.stm32cubemx*.zip -d cubemx_installer chmod +x cubemx_installer/SetupSTM32CubeMX-*.linux ./cubemx_installer/SetupSTM32CubeMX-*.linux - 按图形向导下一步:默认安装到
~/STM32CubeMX(本机即此路径)。一路 Next,勾选同意协议即可。 - 启动:
bash ~/STM32CubeMX/STM32CubeMX或者从应用菜单找 "STM32CubeMX" 图标
[!tip] 想要命令行启动更方便?加个别名到 ~/.bashrc:
echo ”alias cubemx='~/STM32CubeMX/STM32CubeMX &>/dev/null &'” >> ~/.bashrcsource ~/.bashrc
之后终端敲 cubemx 即可启动。
CubeMX 第一次启动要做的
启动后会提示更新固件包(Firmware Package),比如 STM32Cube_FW_F1_V1.8.x。点确认下载——这是各系列芯片的 HAL 库源码,CubeMX 生成工程时要拷贝它。默认存放在 ~/STM32Cube/Repository/。
[!warning] 固件包很大(几百 MB ~ 上 GB)国内下载慢的话,可在 CubeMX 菜单 Help → Updater Settings 里设置代理,或手动从 ST 官网下载 .zip 后解压到 ~/STM32Cube/Repository/,再在 CubeMX 里指定路径。
5. 第四步:安装 VSCode 插件
在 VSCode 里 Ctrl+Shift+X 打开扩展面板,搜索并安装以下插件(按重要程度排序):
| | | |
|---|
| ms-vscode.cpptools | 代码补全、跳转、语法高亮、IntelliSense | |
| marus25.cortex-debug | | |
| ms-vscode.makefile-tools | | |
| ms-vscode.cmake-tools | | |
| cl.eide | | |
命令行一键安装核心三个:
code --install-extension ms-vscode.cpptoolscode --install-extension marus25.cortex-debugcode --install-extension ms-vscode.makefile-tools
6. 第五步:用 CubeMX 生成 Makefile 工程(实战)
这是把「配置」变成「能编译的代码」的关键一步。
6.1 新建工程
- 打开 CubeMX →
File → New Project。 - 搜索你的芯片型号(例如
STM32F103C8T6 → 输 STM32F103C8)→ 选中 → 右上角 Start Project。
6.2 配置外设(举例:点亮 LED + 串口)
- Pinout 视图:点芯片引脚,选功能(如
PC13 设为 GPIO_Output)。 - SYS:
Debug 设为 Serial Wire(务必设!否则烧录一次后 ST-Link 连不上)。 - RCC:
High Speed Clock (HSE) 设为 Crystal/Ceramic Resonator。 - 按需配置 USART、TIM、GPIO……(本笔记不展开,可参考 [[stm32开发与学习/stm32相关调试技巧/stm32 printf重定向UART]])
6.3 时钟配置(关键)
切到 Clock Configuration 标签,让 CubeMX 自动求解。确保HCLK达到目标主频(如 F103 的 72 MHz)。这一步直接影响 SystemClock_Config,配错程序会跑飞。
6.4 项目设置 —— 选 Makefile(本方案核心!)
切到Project Manager标签:
| | |
|---|
Project Name | blink | |
Project Location | /home/你的用户名/stm32project/ | |
Toolchain / IDE | Makefile | |
展开 Code Generator:
| | |
|---|
| ✅ Copy only the necessary library files | |
| Generate peripheral initialization… | | |
| Keep User Code when re-generating | | 重生成时保留你写的代码(USER CODE 区块) |
6.5 生成代码
右上角 GENERATE CODE → 完成。用 VSCode 打开工程目录:
code ~/stm32project/blink
生成的目录结构(典型):
blink/├── blink.ioc# CubeMX 工程文件,以后改配置用它├── Makefile# ⭐ 自带构建脚本,直接 make 就能编译├── Core/│ ├── Inc/# main.h stm32f1xx_it.h …│ └── Src/# main.c stm32f1xx_it.c system_stm32f1xx.c├── Drivers/# HAL 库 + CMSIS│ ├── CMSIS/│ └── STM32F1xx_HAL_Driver/└── build/# make 后生成,含 .elf/.bin/.hex/.map
[!success] CubeMX 生成的 Makefile 是自包含的它已经写好了编译器路径、头文件、链接脚本(.ld)、启动文件(startup_*.s)。你不需要手写任何编译配置,make 一下就能出 .elf。
7. 第六步:配置 VSCode(.vscode 三件套)
在工程根目录建 .vscode/ 文件夹,放三个文件。这三个文件是新手最容易卡的地方,下面给可直接用的模板。
[!important] 把模板里的「你的工程名」替换成实际工程名CubeMX 生成的 elf 叫 工程名.elf(即 Project Name)。例如工程叫 blink,elf 就是 build/blink.elf。
7.1 c_cpp_properties.json —— 智能提示配置
让 VSCode 找到 HAL 库头文件、识别芯片宏。defines 要和你的芯片/Makefile 对应(从 Makefile 的 C_DEFS 段抄)。
{ ”version”: 4, ”configurations”: [ { ”name”: ”STM32”, ”includePath”: [ ”${workspaceFolder}/**”, ”${workspaceFolder}/Core/Inc”, ”${workspaceFolder}/Drivers/STM32F1xx_HAL_Driver/Inc”, ”${workspaceFolder}/Drivers/STM32F1xx_HAL_Driver/Inc/Legacy”, ”${workspaceFolder}/Drivers/CMSIS/Device/ST/STM32F1xx/Include”, ”${workspaceFolder}/Drivers/CMSIS/Include” ], ”defines”: [ ”USE_HAL_DRIVER”, ”STM32F103xB” ], ”intelliSenseMode”: ”gcc-arm”, ”compilerPath”: ”/usr/bin/arm-none-eabi-gcc”, ”cStandard”: ”c11”, ”cppStandard”: ”c++17” } ]}
[!tip] 怎么知道 defines 填什么?打开工程的 Makefile,找 C_DEFS 段,里面会有类似 -DUSE_HAL_DRIVER -DSTM32F103xB,把宏名抄进上面的 defines 数组即可。
STM32F103xB:64KB Flash 的 F103(如 C8T6 实际是 64K 档)STM32F103xH
7.2 tasks.json —— 编译/烧录任务
{ ”version”: ”2.0.0”, ”tasks”: [ { ”label”: ”build”, ”type”: ”shell”, ”command”: ”make -j$(nproc)”, ”group”: { ”kind”: ”build”, ”isDefault”: true }, ”problemMatcher”: [”$gcc”], ”detail”: ”编译工程” }, { ”label”: ”clean”, ”type”: ”shell”, ”command”: ”make clean”, ”problemMatcher”: [], ”detail”: ”清理 build 目录” }, { ”label”: ”rebuild”, ”type”: ”shell”, ”command”: ”make clean && make -j$(nproc)”, ”problemMatcher”: [”$gcc”], ”detail”: ”重新编译” }, { ”label”: ”flash-openocd”, ”type”: ”shell”, ”command”: ”openocd -f interface/stlink.cfg -f target/stm32f1x.cfg -c \”program build/${workspaceFolderBasename}.elf verify reset exit\””, ”dependsOn”: ”build”, ”problemMatcher”: [], ”detail”: ”用 OpenOCD + ST-Link 烧录(推荐,带校验)” }, { ”label”: ”flash-stflash”, ”type”: ”shell”, ”command”: ”st-flash write build/${workspaceFolderBasename}.bin 0x08000000”, ”dependsOn”: ”build”, ”problemMatcher”: [], ”detail”: ”用 st-flash 烧录 .bin 到 0x08000000” } ]}
[!note] 烧录地址 0x08000000这是 STM32 主 Flash 的起始地址(几乎所有 STM32 都一样)。.bin 文件没有地址信息,所以必须指定起始地址;.elf/.hex 自带地址,用 OpenOCD 烧 .elf 最省心。
[!warning] target 配置文件要按芯片系列改tasks.json 和下面的 launch.json 里 target/stm32f1x.cfg 要换成你的芯片系列:
| |
|---|
| target/stm32f1x.cfg |
| target/stm32f4x.cfg |
| target/stm32g4x.cfg |
| target/stm32h7x.cfg |
| target/stm32l4x.cfg |
在 /usr/share/openocd/scripts/target/ 目录能查到全部可选文件。 | |
7.3 launch.json —— 在线调试(断点/单步/变量)
这是最值钱的文件。配好后按 F5 就能打断点调试。
{ ”version”: ”0.2.0”, ”configurations”: [ { ”name”: ”Debug (OpenOCD + ST-Link)”, ”type”: ”cortex-debug”, ”request”: ”launch”, ”cwd”: ”${workspaceFolder}”, ”executable”: ”${workspaceFolder}/build/${workspaceFolderBasename}.elf”, ”servertype”: ”openocd”, ”serverpath”: ”openocd”, ”gdbPath”: ”gdb-multiarch”, ”device”: ”ST-Link”, ”configFiles”: [ ”interface/stlink.cfg”, ”target/stm32f1x.cfg” ], ”searchDir”: [”/usr/share/openocd/scripts”], ”runToEntryPoint”: ”main”, ”showDevDebugOutput”: ”raw”, ”svdFile”: ”” } ]}
关键字段解释:
| | |
|---|
executable | build/工程名.elf | |
servertype | openocd | |
gdbPath | gdb-multiarch | ⭐ Ubuntu 关键!不是 arm-none-eabi-gdb |
configFiles | | |
searchDir | /usr/share/openocd/scripts | |
runToEntryPoint | main | |
[!tip] 想看寄存器?Cortex-Debug 调试时左侧会自动出现 REGISTER / WATCH / VARIABLES 面板。想看外设寄存器,下载对应芯片的 .svd 文件填到 svdFile,即可图形化查看外设寄存器。SVD 文件在 CubeMX 固件包里能找到。
8. 完整工作流速览(日常开发就这几步)
操作对应:
- 改外设配置 → 回 CubeMX 改
.ioc → GENERATE CODE(你的 USER CODE 不会丢)。 - 写业务代码 → 在 VSCode 的
USER CODE BEGIN/END 区块内写。 - 编译 →
Ctrl+Shift+B → 选 build(或直接回车,它已是默认)。 - 调试 → 打断点 →
F5(Cortex-Debug 自动编译→烧录→停在 main)。 - 只烧录不调试 →
Ctrl+Shift+P → Tasks: Run Task → flash-openocd。
9. 一键自检脚本(环境体检)
把下面存成 check_stm32_env.sh,随时检查环境是否完整:
#!/bin/bashgreen=”\033[32m”; red=”\033[31m”; reset=”\033[0m”check() { if command -v ”$1” >/dev/null 2>&1; then echo -e ”${green}[✓]${reset} $1 → $(command -v $1)” else echo -e ”${red}[✗]${reset} $1 未安装” fi}echo ”=== STM32 开发环境自检 ===”check arm-none-eabi-gcccheck arm-none-eabi-objcopycheck arm-none-eabi-sizecheck makecheck cmakecheck gdb-multiarchcheck openocdcheck st-flashcheck codeecho ””echo ”=== CubeMX ===”[ -x ”$HOME/STM32CubeMX/STM32CubeMX” ] && echo -e ”${green}[✓]${reset} STM32CubeMX 已安装” || echo -e ”${red}[✗]${reset} 未找到 ~/STM32CubeMX”echo ””echo ”=== udev 规则 ===”ls /lib/udev/rules.d/ | grep -q stlink && echo -e ”${green}[✓]${reset} ST-Link udev 规则存在” || echo -e ”${red}[✗]${reset} 缺少 udev 规则”echo ””echo ”=== VSCode 嵌入式插件 ===”code --list-extensions 2>/dev/null | grep -q cortex-debug && echo -e ”${green}[✓]${reset} Cortex-Debug” || echo -e ”${red}[✗]${reset} 缺 Cortex-Debug”code --list-extensions 2>/dev/null | grep -q cpptools && echo -e ”${green}[✓]${reset} C/C++” || echo -e ”${red}[✗]${reset} 缺 C/C++”
运行:
chmod +x check_stm32_env.sh./check_stm32_env.sh
全绿即环境就绪。
10. 常见问题(FAQ)
Q1:make 报错 arm-none-eabi-gcc: not found
工具链没装好,回到第 2 步重装 gcc-arm-none-eabi,并确认 arm-none-eabi-gcc --version 能输出版本。
Q2:调试报错 arm-none-eabi-gdb not found / Couldn't find gdb
99% 是gdbPath写成了arm-none-eabi-gdb。Ubuntu 上改成 gdb-multiarch(见 7.3)。
Q3:OpenOCD 报 Error: open failed / no device found
- 检查 ST-Link USB 线(要数据线,不是充电线)。
lsusb | grep -i stlink- 回第 3 步检查 udev 规则 + 用户组权限。
- 确认 CubeMX 里
SYS → Debug = Serial Wire,否则芯片 SWD 被关,连不上(解决方法见 [[stm32开发与学习/stm32相关调试技巧/stm32 无法烧录的解决办法(使用boot)]])。
Q4:烧录一次后 ST-Link 就连不上了
芯片的 SWD 引脚被你的代码重新复用成 GPIO 了,或 SYS→Debug 没设 Serial Wire。用BOOT0=1进入串口/ISP 模式擦除恢复。详见 [[stm32开发与学习/stm32相关调试技巧/stm32 无法烧录的解决办法(使用boot)]]。
Q5:VSCode 红波浪线一片(找不到 HAL 头文件)
c_cpp_properties.json 的 includePath 没覆盖到所有头文件目录,或 defines 的芯片宏不对。打开 Makefile 的 C_INCLUDES 和 C_DEFS,对照补全。
Q6:CubeMX 重新生成代码后,我写的代码没了?
必须写在 /* USER CODE BEGIN xxx / 和 / USER CODE END xxx */ 之间,CubeMX 只保留这些区块内的内容。
Q7:串口看不到 printf 输出?
需要重定向 fputc 并勾选 Use MicroLIB(Keil)或对 GCC 实现 _write/__io_putchar。参考 [[stm32开发与学习/stm32相关调试技巧/stm32 printf重定向UART]]。
11. 进阶:CMake 工程(可选)
较新版本的 CubeMX 支持 Toolchain/IDE = CMake。如果你更习惯 CMake:
- CubeMX 里 Project → Toolchain 选
CMake(无则用 Makefile,二者皆可)。 - 工程根目录会出现
CMakeLists.txt 和一个 cmake/ 工具链文件。 - VSCode 用
CMake Tools 插件,选 arm-none-eabi-gcc 工具链 kit,即可 F7 编译。 - 调试配置同第 7.3 节,只是
executable 路径变成 build/工程名.elf(CMake 输出目录可能不同,按实际改)。
[!note] 新手建议先用 MakefileCubeMX 的 Makefile 方案最成熟、踩坑最少。等熟悉了再迁移 CMake。本机实测 Makefile 工程 make -j8 几秒编译完。
12. 本机实测环境快照
[!summary] 写作本笔记时的真实环境以下即「全绿」状态,可作为对照基准:
- OS:Ubuntu 24.04.4 LTS (x86_64)
- VSCode:1.127.0,插件
cpptools / cortex-debug / cmake-tools / makefile-tools 等 - arm-none-eabi-gcc:13.2.1(apt
gcc-arm-none-eabi 15:13.2.rel1-2) - newlib:4.4.0 | make:4.3 | cmake:3.28.3
- gdb-multiarch:15.1 ⭐(调试器)
- openocd:0.12.0(
/usr/local/bin/openocd,脚本 /usr/share/openocd/scripts) - stlink:v1.8.0(st-flash / st-info)
- STM32CubeMX:6.16(
~/STM32CubeMX,自带 JRE) - Java:OpenJDK 21(系统级,CubeMX 自带的不依赖它)
- udev:ST-Link V1/V2/V2-1/V3 规则齐全
附录 A:Windows + WSL2 用户适配
[!info] 谁需要看这一节如果你被迫用 Windows、又想要 Linux 工具链的体验(arm-none-eabi-gcc / make / openocd),可以在 WSL2 里跑这套方案。物理机 Linux 用户(本笔记主场景)可直接跳过本节。
A.1 一句话结论
能用,方案成熟(微软官方支持)。但要分环节看:编译、CubeMX 图形界面、串口监控几乎零障碍,只有「USB 烧录 + 在线调试」这一步需要用usbipd-win做设备直通,外加几个小坑。
| | |
|---|
make | | |
| | Win11 的 WSLg 直接显示 Linux GUI,免装 X server |
| | 设备直通后出现 /dev/ttyACM0,minicom 正常用 |
| | ST-Link 是 USB 设备,WSL 默认看不到,需 usbipd-win 直通 |
A.2 三条路线(按推荐度)
| | |
|---|
| usbipd 把 ST-Link 直通进 WSL,烧录/调试全在 WSL 跑 | 想要一体化 Linux 体验、能接受少量 USB 折腾 |
| WSL 只 make 出 .elf/.bin,烧录用 Win 端 STM32CubeProgrammer | |
| | |
[!tip] 路线 B 为什么最省心烧录器始终在 Windows 原生驱动下工作,最稳。代价只是 WSL 编译出的 .bin 要拿到 Windows 端烧——用 VSCode Remote-WSL 编辑,文件在 \\wsl$\... 路径下 Windows 可直接访问,基本无感。
A.3 路线 A 全链路:usbipd-win 直通三步
① Windows 端(PowerShell 管理员)装并绑定设备:
winget install --interactive dorssel.usbipd-win# 装 usbipd-winusbipd list# 找到 ST-Link 的 BUSIDusbipd bind --busid# 绑定(每设备只需一次)usbipd attach --wsl --busid# 转交给 WSL# 想拔插自动转交:usbipd attach --wsl --busid --auto-attach
② WSL2 端确认设备到位,再装工具链(命令同本笔记第 2 步):
sudo apt install -y gcc-arm-none-eabi libnewlib-arm-none-eabi make gdb-multiarch openocd stlink-toolslsusb# 看到 ST-Link → 直通成功st-info --probe# 能列出目标芯片
③ VSCode +.vscode三件套原样套用(见第 7 节)—— WSL 里同样要装 gdb-multiarch,gdbPath 同样写 gdb-multiarch。用 VSCode 的Remote-WSL打开工程目录即可,编译/调试体验与物理机一致。
A.4 ⚠️ 全 WSL 路线的 4 个坑
- 互斥占用:ST-Link attach 到 WSL 后,Windows 端不能同时用(含 ST 官方 GUI)。要取回:
usbipd detach --busid <BUSID>。 - 拔插 / 重启失效:USB 一断就要重新
attach。用 --auto-attach 保持常驻。 - ST-Link V3 偶发连接失败:V3 是复合设备(调试 + VCP + …),社区报告过 OpenOCD 连不上,需把整个复合设备一起 attach;V2 / V2-1 最省心。
- 内核版本:需较新的 WSL2 内核(支持 USB/IP),先
wsl --update 升级一次。
A.5 WSL 参考资料
- Microsoft Learn — 在 WSL2 中连接 USB 设备(官方)
- usbipd-win Wiki — WSL support
- McUonEclipse 2025 — 在 WSL2/Docker 里用 USB 调试探针
13. 参考与延伸阅读
- [[stm32开发与学习/stm32相关调试技巧/stm32 linux环境下的调试方法(使用stlink)]]
- [[stm32开发与学习/stm32相关调试技巧/stm32 无法烧录的解决办法(使用boot)]]
- [[stm32开发与学习/stm32相关调试技巧/stm32 printf重定向UART]]
[!quote] 一句话总结sudo apt install 装齐工具链 + 插件 → CubeMX 选 Makefile 生成工程 → VSCode 配 .vscode 三件套(记得 gdb-multiarch)→ Ctrl+Shift+B 编译 / F5 调试。 就这么个闭环,配一次,受益一辈子。