拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

VS Code + CMake + OpenOCD:通用MCU开发环境搭建全指南

VS Code + CMake + OpenOCD:通用MCU开发环境搭建全指南

近几年做MCU开发,我用过Keil、IAR、STM32CubeIDE,最后主力环境换成了 VS Code + CMake + Make + GNU工具链 + OpenOCD 这一套。第一次有人跟我推荐这套组合时,我也觉得折腾,但真正跑通之后,收益远超预期:跨平台、可脚本化、不受厂商IDE绑架,最重要的是可以在一套编辑器里同时处理固件、上位机乃至测试脚本。这篇文章我会从零开始,把通用MCU开发环境怎么搭、每个环节为什么这么做、实际调试烧录时有哪些坑,一次性讲清楚。无论你是刚接触STM32、国民技术这类ARM Cortex-M单片机,还是被厂商IDE的工程格式折磨已久的老手,都可以按步骤复现,RISC-V平台的差异我会在最后说明。

1. 四个工具分别干什么,为什么组合在一起

1.1 先说结论:这是一套可替换的流水线

MCU开发流程其实就三件事:写代码、编出固件、把固件烧进芯片里再调试。厂商IDE是把这三件事打包在一起,看起来很省事,但你一旦需要自定义构建脚本、接持续集成,或者换一个品牌MCU,工程迁移成本就很高。

这套方案把流程拆开。VS Code 只做界面和任务调度,让你在同一个窗口里完成编辑、编译、烧录、打断点。CMake 负责描述工程:有哪些源文件、用什么编译选项、链接脚本放在哪里,它不直接生成固件。Make 是执行者,CMake 生成 Makefile 之后,Make 根据依赖关系调用编译器,实现增量编译。GNU 工具链是真正干“编和链”的活的人,arm-none-eabi-gcc 把 C/汇编变成机器码,ld 完成地址分配。OpenOCD 是调试和烧录的“翻译官”,通过 ST-Link、J-Link、DAPLink 这类调试器,把电脑发出的 GDB 命令或烧录指令翻译成芯片能听懂的 SWD/JTAG 时序。

从底层到上层,整条链路是这样转起来的:VS Code 收到“编译”指令,调用 CMake 生成 Makefile,Make 再去调 GCC,产出 ELF/BIN/HEX 固件;烧录时 OpenOCD 连接调试器,把固件写入芯片内部 Flash;调试时 OpenOCD 作为 GDB Server,arm-none-eabi-gdb 作为客户端,实现源码级断点、变量查看和单步。每一环都可以独立替换,这就是“通用”二字的底气。

1.2 为什么有了CMake还要Make,两者不是二选一

很多刚入门的同学会把 CMake 和 Make 搞混,问出“既然用了CMake,为什么还要Make”这类问题。其实这是“设计图”和“施工队”的关系。CMake 是设计图,Make 是施工队。CMake 本身不直接编译,它根据 CMakeLists.txt 生成一份 Makefile(如果指定 Ninja,则生成 Ninja 文件),之后由 Make 逐条执行编译和链接命令。

直接手写 Makefile 当然也能做嵌入式工程,但跨平台、库依赖、编译选项管理会很快变得混乱。CMake 的好处是生成式管理:你写一次 CMakeLists,就能在 Windows、Linux、macOS 上生成对应的 Makefile,还能一键切换到 Ninja 并行构建。在嵌入式场景里还有个更大的好处:通过 toolchain 文件,同一份 CMake 逻辑可以切换 ARM GCC、RISC-V GCC,甚至本机 x86 GCC,方便做单元测试。

所以不要纠结“CMake能不能代替Keil”——CMake 完全不替代 IDE 的调试界面,它替代的是 Keil 里那个 uvprojx 工程文件。调试和烧录那一半,由 OpenOCD 和 VS Code 补齐。理解了这一点,你看下面的配置就不会觉得是多余动作。

1.3 这套组合和厂商IDE到底怎么选

如果你只维护一个项目、一个芯片、一个人开发,厂商IDE确实够用。但团队一扩大,问题就来了:Keil 工程在Linux上没法构建,CubeIDE 的工程文件跨版本会变,IAR 的编译器只有Windows版本。你总不能让每个工程师都装一模一样的IDE和破解版许可证。

用这套开源组合,工程描述变成了纯文本的 CMakeLists.txt 和 toolchain 文件。代码提交到Git之后,任何人拉下来都能用同一条命令构建,CI 服务器也能跑同样的命令。即使团队里有同事坚持用 Keil,你也可以保留一份 CMakeLists 作为“唯一真源”,Keil工程作为手动维护的发布附件。这套组合不是让你今天就必须抛弃原有IDE,而是给你一个不受厂商绑定的备选方案。

2. 环境安装与版本验证,Windows 和 Ubuntu 双路线

2.1 Windows 下安装 VS Code、CMake、GNU 工具链和 OpenOCD

Windows 下装这套环境是绝大多数人第一步遇到坑的地方。先装 VS Code,安装包用 User Installer 即可,不需要管理员权限。装完以后打开扩展面板,至少要装这三个插件:C/C++(ms-vscode.cpptools)负责语法解析和 IntelliSense,CMake Tools 负责识别 CMakeLists 和编译任务,Cortex-Debug 负责对接 OpenOCD 做调试。其中 C/C++ 插件比较大,如果网络不好会卡,耐心等它装完。

然后装 CMake。去官网下载 Windows x86_64 的 msi 安装包,安装时记得勾选“Add CMake to system PATH”。装完以后重新打开终端,输入cmake --version确认。很多人遇到“无法将‘cmake’项识别为 cmdlet”就是这个PATH没配对,或者终端没有重启。

GNU ARM 工具链建议直接下载 Arm 官方提供的 arm-none-eabi 工具链,Windows 版本有 exe 安装包和 zip 免安装包。我习惯用 zip 版,解压到C:\tools\arm-gnu-toolchain,然后把bin目录加进 PATH。验证方式是在新开的终端里输入arm-none-eabi-gcc --version,能看到版本号就说明OK。

OpenOCD 在 Windows 上推荐用 xPack 发布的版本,它的包内部已经带了 libusb 和 WinUSB 驱动。解压后同样把bin目录加进 PATH,验证openocd --version。还有一个隐形步骤容易被忽略:如果你的调试器是 ST-Link 或 J-Link,Windows 需要安装对应的USB驱动,否则 OpenOCD 会提示找不到设备。

最后是 Make。Windows 没有原生 make,我建议装一个 MSYS2,在 MSYS2 shell 里执行pacman -S mingw-w64-x86_64-make,装完以后mingw32-make.exe就在 PATH 里了。你也可以用 MinGW-w64 自带的 mingw32-make,道理一样。注意不要用 Visual Studio 的 nmake,它和 CMake 生成的 Unix Makefile 不兼容。

2.2 Ubuntu 下一条命令装完基础环境,但是版本有讲究

Linux 下的安装比 Windows 省心很多,但版本坑需要注意。以 Ubuntu 22.04 为例,打开终端执行:

sudo apt update sudo apt install -y build-essential cmake gcc-arm-none-eabi openocd gdb-multiarch

build-essential里带了 make 和 gcc;gcc-arm-none-eabi是ARM交叉编译器;openocd是调试烧录服务;gdb-multiarch是多架构 GDB,可以代替 arm-none-eabi-gdb,在调试时少一个工具链安装问题。装完以后验证一下版本:

cmake --version make --version arm-none-eabi-gcc --version openocd --version gdb-multiarch --version

Ubuntu 源里的 OpenOCD 版本通常比较旧,如果你用的是新出的 MCU,OpenOCD 的 target 文件里可能根本没有这款芯片。这时需要自己编译新版 OpenOCD,步骤不复杂:

git clone https://github.com/openocd-org/openocd.git cd openocd ./bootstrap ./configure --enable-stlink --enable-jlink --enable-cmsis-dap make -j$(nproc) sudo make install

自己编译时--enable那一串编译选项决定了支持哪些调试器,建议把常见的都打开。编译过程需要 autoconf、automake、libtool、libusb-dev 等依赖,缺什么就 apt 装什么。

2.3 版本怎么选?直接给一张参考表

很多老手会告诉你“最新版最好”,但在嵌入式工具链上我建议保守一点。GCC 版本太新,编译旧工程可能会出现新的警告甚至错误;OpenOCD 版本太旧,新芯片的烧录算法和支持文件又缺失。我常用的组合参考如下:

工具最低建议版本备注
VS Code1.80+扩展市场更新即可
CMake3.16+太低不支持 toolchain 文件的某些写法
GNU ARM 工具链10.3+10.3 比较稳,12.x 开始默认启用新警告
Make4.3+用 MSYS2 或 MinGW 版本均可
OpenOCD0.11+新 MCU 建议 0.12 或自己编译最新版

选完版本后,建议把工具链的 bin 目录写进用户环境变量,而不是再额外复制一份到项目目录里。环境变量是全局的,项目路径不会因为换电脑而失效。

3. 构建工程:CMakeLists 的设计与生成

3.1 推荐一个干净的工程目录结构

很多厂商生成的工程把所有文件堆在一起,看起来非常难受。我不建议在源码目录里直接跑 CMake,而是在项目根目录放一份 CMakeLists.txt,把构建产物全部扔到 build 目录里。推荐的目录布局是这样的:

project/ ├── CMakeLists.txt ├── cmake/ │ └── toolchain-arm-none-eabi.cmake ├── src/ │ ├── main.c │ ├── startup_stm32f407xx.s │ └── system_stm32f4xx.c ├── include/ │ └── main.h ├── linker/ │ └── stm32f407vgtx_flash.ld ├── openocd/ │ └── board/stm32f4discovery.cfg ├── .vscode/ │ ├── tasks.json │ ├── launch.json │ └── c_cpp_properties.json └── build/

cmake目录放交叉编译工具链文件,linker目录放链接脚本,openocd目录放调试器配置。这样设计的好处是,当你换芯片或者换调试器时,只需要替换对应的配置文件和链接脚本,CMakeLists 的主体不用动。

3.2 工具链文件怎么写,为什么必须写

CMake 默认会调用本机编译器,也就是 gcc/clang,这显然不能用来编 ARM 固件。所以需要一份 toolchain 文件告诉 CMake:目标平台不是本机,请使用交叉编译器。下面是一个针对 ARM Cortex-M4 的示例:

set(CMAKE_SYSTEM_NAME Generic) set(CMAKE_SYSTEM_PROCESSOR cortex-m4) set(CMAKE_C_COMPILER arm-none-eabi-gcc) set(CMAKE_CXX_COMPILER arm-none-eabi-g++) set(CMAKE_ASM_COMPILER arm-none-eabi-gcc) set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)

其中CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY这一行很关键。CMake 在配置阶段会尝试编译一个小的可执行程序来判断编译器是否可用,但嵌入式环境没有操作系统,链接可执行文件容易失败,所以让 CMake 编译一个静态库来测试,能避免很多莫名其妙的配置报错。

3.3 CMakeLists 核心片段:从源码到 ELF/BIN/HEX

写 CMakeLists 时,我不喜欢用file(GLOB_RECURSE)去自动收集源文件,因为这种写法新增文件后 CMake 不会立刻感知,很容易出现“明明加了文件,编译却没带上”的问题。如果你图省事,一定要用 GLOB,就加CONFIGURE_DEPENDS后缀。更稳的做法是手动列出源文件,虽然麻烦一点,但可控性强。

一个典型的嵌入式 CMakeLists 可以这样写:

cmake_minimum_required(VERSION 3.16) project(mcu_demo C ASM) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(LINKER_SCRIPT ${CMAKE_SOURCE_DIR}/linker/stm32f407vgtx_flash.ld) set(SOURCES src/main.c src/startup_stm32f407xx.s src/system_stm32f4xx.c ) add_compile_options(-mcpu=cortex-m4 -mthumb -O2 -Wall -ffunction-sections -fdata-sections) add_executable(${PROJECT_NAME}.elf ${SOURCES}) target_link_options(${PROJECT_NAME}.elf PRIVATE -T ${LINKER_SCRIPT} -Wl,--gc-sections ) add_custom_command(TARGET ${PROJECT_NAME}.elf POST_BUILD COMMAND ${CMAKE_OBJCOPY} -O ihex ${PROJECT_NAME}.elf ${PROJECT_NAME}.hex COMMAND ${CMAKE_OBJCOPY} -O binary ${PROJECT_NAME}.elf ${PROJECT_NAME}.bin COMMAND ${CMAKE_SIZE} ${PROJECT_NAME}.elf )

-ffunction-sections -fdata-sections配合链接阶段的-Wl,--gc-sections,可以把没有用到的函数和数据从最终固件里剔除,这对MCU这种 Flash 有限的场景特别重要。CMAKE_OBJCOPY和CMAKE_SIZE是 CMake 在 toolchain 文件里自动推导的变量,不用手动指定,但前提是工具链文件里设置的编译器名称能被正确识别。

3.4 用 Make 驱动构建,一条命令从配置到编译

有了上面的 CMakeLists,在项目根目录执行:

cmake -S . -B build -G "Unix Makefiles" \ -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm-none-eabi.cmake \ -DCMAKE_BUILD_TYPE=Debug

-S . -B build的意思是源码目录是当前目录,构建目录是build。-G "Unix Makefiles"指定生成 Makefile;在 Windows 的 MSYS2/MinGW 环境下,可以用-G "MinGW Makefiles",或者把 mingw32-make 复制为 make.exe 继续用 Unix Makefiles。-DCMAKE_TOOLCHAIN_FILE指向我们上面写的工具链文件。接下来执行:

cmake --build build -- -j$(nproc)

cmake --build会调用生成器对应的构建命令,这里就是 make,--后面的参数原样传给 make,-j$(nproc)表示用满CPU核心并行编译。编译结束后,build目录下会同时出现.elf、.hex、.bin三个文件,这就是最终固件。

如果你更习惯直接敲 make,也可以先cd build,然后make -j。这两种方式本质一样,只是前者封装了一层,更不容易打错路径。

4. VS Code 配置:编译、烧录、调试一条龙

4.1 用 tasks.json 实现一键编译,不用再敲命令行

命令行跑通以后,就可以把构建过程收进 VS Code。在项目根目录创建.vscode/tasks.json,下面是一个可以直接抄的版本:

{ "version": "2.0.0", "tasks": [ { "label": "cmake-configure", "type": "shell", "command": "cmake", "args": [ "-S", "${workspaceFolder}", "-B", "${workspaceFolder}/build", "-G", "Unix Makefiles", "-DCMAKE_TOOLCHAIN_FILE=${workspaceFolder}/cmake/toolchain-arm-none-eabi.cmake", "-DCMAKE_BUILD_TYPE=Debug" ], "group": "build", "problemMatcher": [] }, { "label": "build", "type": "shell", "command": "cmake", "args": [ "--build", "${workspaceFolder}/build", "--", "-j4" ], "group": { "kind": "build", "isDefault": true }, "dependsOn": ["cmake-configure"] } ] }

配置里dependsOn的作用是:第一次按Ctrl+Shift+B时,先执行 cmake-configure,再执行 build;以后如果 CMakeLists 没变,cmake --build 会自动跳过重复配置。这里我故意写-j4而不是-j,因为在 Windows 上$(nproc)不存在,VS Code 的 shell 任务里写死 4 线程更稳妥。

4.2 用 launch.json 对接 OpenOCD 和 GDB

编译只是第一步,能按 F5 进调试才是这套环境最爽的地方。要用的插件是 Cortex-Debug,安装后新建.vscode/launch.json:

{ "version": "0.2.0", "configurations": [ { "name": "OpenOCD Debug", "cwd": "${workspaceRoot}", "type": "cortex-debug", "request": "launch", "servertype": "openocd", "interface": "swd", "configFiles": [ "interface/stlink.cfg", "target/stm32f4x.cfg" ], "searchDir": [ "C:/OpenOCD/scripts" ], "executable": "${workspaceFolder}/build/mcu_demo.elf", "svdFile": "${workspaceFolder}/STM32F407.svd", "gdbPath": "arm-none-eabi-gdb", "runToEntryPoint": "main" } ] }

servertype必须是openocd,告诉 Cortex-Debug 启动一个 OpenOCD 服务。configFiles里的两个文件对应 OpenOCD 的接口配置和目标芯片配置:interface/stlink.cfg表示调试器是 ST-Link,target/stm32f4x.cfg表示目标芯片是 STM32F4 系列。如果你用的是 J-Link,就把interface/stlink.cfg换成interface/jlink.cfg;如果用的是 DAPLink,就换成interface/cmsis-dap.cfg。

searchDir是 OpenOCD 脚本所在目录,Windows 上必须写绝对路径。gdbPath指定 arm-none-eabi-gdb;在 Ubuntu 上也可以改成gdb-multiarch。svdFile是芯片的外设寄存器描述文件,填了之后调试窗口里可以直接看寄存器和外设的值,没有也能调试,但体验差很多。runToEntryPoint: main表示启动后在 main 函数处暂停,比默认停在启动汇编里友好得多。

4.3 c_cpp_properties.json 和头文件红色波浪线

很多人在 VS Code 里打开工程,发现#include下面一片红色波浪线,这不是代码错误,而是 C/C++ 插件不知道去哪里找头文件,也不知道定义了哪些宏。解决方法是配置.vscode/c_cpp_properties.json:

{ "configurations": [ { "name": "MCU", "includePath": [ "${workspaceFolder}/include", "${workspaceFolder}/src" ], "defines": [ "STM32F407xx" ], "compilerPath": "arm-none-eabi-gcc", "cStandard": "c11" } ], "version": 4 }

includePath要包含所有头文件目录,defines里填的是编译时才会定义的宏,比如 HAL 库经常需要STM32F407xx这样的宏来区分芯片型号。如果编译用的是 CMake,更推荐在 CMakeLists 里设置set(CMAKE_EXPORT_COMPILE_COMMANDS ON),然后在c_cpp_properties.json里补一行"compileCommands": "${workspaceFolder}/build/compile_commands.json",让插件直接从编译数据库中读取所有路径和宏定义,一劳永逸。

5. OpenOCD 实操:烧录、调试与常见报错

5.1 命令行手动烧录:理解 OpenOCD 到底做了什么

调试器配置好以后,不一定每次都要进 VS Code。很多情况下你只想快速烧个固件,那直接在命令行敲:

openocd -f interface/stlink.cfg -f target/stm32f4x.cfg \ -c "program build/mcu_demo.elf verify reset exit"

这条命令加载了接口配置和目标配置,然后执行program命令。OpenOCD 会通过 ST-Link 以 SWD 协议访问 MCU 的调试接口,找到内部 Flash 控制器,完成擦除、写入和校验。最后verify做读回校验,reset复位芯片,exit让 OpenOCD 退出。

这里也回答一个很多新人疑惑的问题:MCU 内部的 Flash 到底用什么接口访问?并不是你把飞线接到 Flash 引脚上,而是通过 SWD/JTAG 调试接口,由芯片内部的 Flash 控制器去擦写 Flash 区域。OpenOCD 只是把烧录指令翻译给调试器,最终操作 Flash 的是芯片自己。这也是为什么在 target 配置文件里必须写对芯片型号,因为不同芯片的 Flash 控制器寄存器地址和操作时序差别很大。

5.2 “openocd server is not running!” 这类报错怎么排查

使用 VS Code 调试时,最常见的报错之一就是:“can't perform jtag flash, because openocd server is not running!”。看到这个提示先别慌,它说明 Cortex-Debug 想操作 OpenOCD,但 OpenOCD 进程没有成功跑起来。常见原因有四类。

第一,OpenOCD 可执行文件没在 PATH 里,或者 launch.json 里没有指定绝对路径。解决方法是先打开一个终端,敲openocd --version确认能不能找到。

第二,configFiles里的脚本路径不对,OpenOCD 启动后立刻报错退出。解决方法是手动执行:

openocd -f interface/stlink.cfg -f target/stm32f4x.cfg

如果输出停在Info : Listening on port 3333,说明 OpenOCD 已经跑起来了;如果报Error: open failed,就是路径或脚本文件名写错了。

第三,调试器和目标板接线有问题。OpenOCD 启动时如果找不到目标芯片,会出现Error: init mode failed或者超时的提示。检查 SWDIO/SWCLK/GND 三条线是否接对,目标板是否上电。

第四,3333 端口被占用。如果之前有一个异常退出的 OpenOCD 进程没杀干净,新进程起不来。在 Windows 上可以开任务管理器找 openocd 进程,Linux 上用pkill openocd。

5.3 外部 Flash、JTAG 和芯片保护,常见问题速查表

除了 OpenOCD server 报错,我还整理过一张高频问题速查表,基本都是团队同事踩过的坑:

症状可能原因解决方法
CMake 提示无法识别命令PATH 没配置,或终端未重启把 cmake 安装目录加 PATH,重开终端
VS Code 任务报 “unable to find suitable visual studio toolc...”CMake 默认生成器选了 VS配置里加-G "Unix Makefiles"或-G "Ninja"
头文件红色波浪线includePath 或 defines 没配配置 c_cpp_properties.json 或 compile_commands
OpenOCD 找不到设备USB驱动缺失/Linux权限不够Windows 重装调试器驱动;Linux 加 udev 规则
program 报 verify 失败芯片Flash读保护开启或接线不稳定检查 SWD 线,确认芯片没有锁死
GDB 连不上 OpenOCD端口 3333 被占用杀掉占用进程,确认 OpenOCD 在运行
烧录外部 QSPI Flash 失败OpenOCD 缺少外部 Flash loader使用厂商工具或额外加载 loader 脚本

Linux 下 OpenOCD 权限问题很常见,建议把 OpenOCD 自带的 udev 规则文件复制到系统目录:

sudo cp /usr/share/openocd/contrib/60-openocd.rules /etc/udev/rules.d/ sudo udevadm control --reload-rules

重新插拔调试器以后,普通用户就能直接访问 USB 设备,不用每次 sudo。

6. 踩坑心得与后续扩展

6.1 先用命令行跑通,再碰 VS Code 配置

这大概是我最想强调的一点。很多人一上来就照着网上的 launch.json 一顿复制,结果按 F5 报错,然后又不知道错在哪。我的建议是:先完全抛开 VS Code,在终端里把cmake --build跑到能生成 bin,再把openocd -c "program ..."跑到能烧录,最后才去配置 tasks.json 和 launch.json。这样一旦配置出问题,你能确定是 VS Code 这层的问题,还是工具链或硬件的问题。

另外,VS Code 的 C/C++ 插件第一次加载一个大工程时,会花较长时间建立索引,期间红色波浪线可能一直在跳动。不要急着改配置,等索引完成再说。如果加了 compile_commands.json 还不行,可以试试C/C++: Reset IntelliSense Database命令。

6.2 Make 不是只能编固件,还能帮你做自动化和 CI

CMake + Make 这套组合最大的优势在于可以脚本化。你可以在仓库里放一个build.sh:

#!/bin/bash set -e cmake -S . -B build -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release cmake --build build -j$(nproc) openocd -f interface/stlink.cfg -f target/stm32f4x.cfg -c "program build/mcu_demo.elf verify reset exit"

这样不管是本地手动构建、开发机上自动构建,还是 CI 流水线,都执行同一份脚本。GitHub Actions 或者 GitLab CI 里只需要装上相同版本的 gcc-arm-none-eabi、cmake、make、openocd,其余的交给脚本完成。这个能力是厂商 IDE 很难给你的。

6.3 这套方案不是银弹,遇到特殊芯片要灵活切换

不要以为所有 MCU 都能用同一份 OpenOCD 配置搞定。有些新出的国产芯片、专用 SoC,OpenOCD 的目标文件还没有正式支持。这时候几种替代方案我实测下来比较靠谱:第一,用芯片厂商提供的 OpenOCD 分支,很多厂家会维护自己的 fork;第二,用厂商自己的命令行烧录工具,比如 STM32CubeProgrammer CLI,然后依然保留 VS Code 做编辑和构建,只把烧录命令换成厂商工具;第三,自己照着 OpenOCD 文档编写 target 配置文件,这个门槛高一点,但只要搞懂寄存器就可行。

那“通用”二字是不是白说了?也不算。通用强调的是流程和思路通用,而不是一个配置文件走天下。你掌握了 CMake 组织工程和 OpenOCD 调试模型,换芯片只是替换工具链后缀和配置文件,远比换一个 IDE 来得轻。

6.4 最后分享一个我一直在用的小技巧

在 Windows 上我习惯把工具链都装到同一个根目录,比如C:\tools\,然后给 VS Code 的终端设置一个环境变量文件。这样多台电脑换着用,只要同步一个环境变量清单,新电脑十分钟就能恢复到熟悉环境。在 Ubuntu 上我则习惯在~/.bashrc里写一组 alias:

alias mcu-build='cmake --build build -j$(nproc)' alias mcu-flash='openocd -f interface/stlink.cfg -f target/stm32f4x.cfg -c "program build/mcu_demo.elf verify reset exit"'

这样编译和烧录都只要敲两个短命令,手指肌肉记忆形成以后,效率真的比打开 IDE、点编译、点下载快很多。我个人体会是,环境折腾这件事,前期越愿意花时间理解每层工具的关系,后面开发就越顺手。如果你现在还在用双击编译的方式做 MCU 开发,不妨找个周末按这套方案搭一次,哪怕只是点个灯,你对编译、链接、调试接口的认知会完全不一样。

返回列表