本文记录本工程在 Ubuntu 22.04 下,通过 ATK ATK-HS-V3-CMSIS-DAP 烧录器编译并烧录 STM32F407ZGTx 的完整流程。
当前工程信息:
- 工程目录:
/home/sg/aaaa - MCU:
STM32F407ZGT6 - pyOCD target 名称:
stm32f407zgtx - CMake preset:
Debug - 编译产物:
/home/sg/aaaa/build/Debug/aaaa.elf - 烧录器:
ATK ATK-HS-V3-CMSIS-DAP
1. 硬件连接
CMSIS-DAP 和目标板至少需要连接以下信号:
text
DAP SWDIO -> 目标板 SWDIO
DAP SWCLK -> 目标板 SWCLK
DAP GND -> 目标板 GND
DAP VTref -> 目标板 3.3V 参考电压
注意:
- 目标板必须供电。
- DAP 和目标板必须共地。
- 如果目标板自己供电,DAP 的
VTref/3V3 sense需要接到目标板 3.3V,用于检测目标电压。 - 如果连接失败,可以降低 SWD 频率,例如烧录时加
--frequency 1000000。
2. 检查工具链
本工程使用 CMake + Ninja + arm-none-eabi-gcc 编译,使用 pyOCD 烧录。
各工具的作用:
CMake:负责生成构建系统。它读取CMakeLists.txt和CMakePresets.json,根据工程配置、源文件、头文件路径、编译宏、链接脚本和工具链文件,生成 Ninja 可以执行的构建文件。CMake 本身通常不直接编译代码。Ninja:负责实际调度编译任务。CMake 生成build.ninja后,Ninja 根据依赖关系调用编译器、汇编器和链接器。Ninja 的特点是速度快、输出简洁,适合嵌入式工程反复增量编译。arm-none-eabi-gcc:ARM Cortex-M 裸机交叉编译器。它把 C 代码、启动汇编文件编译链接成 STM32 可以运行的 ELF 固件。这里的none-eabi表示目标环境不是 Linux/Windows 这类操作系统,而是裸机或 RTOS 环境,ABI 使用 ARM Embedded ABI。pyOCD:Python 编写的 Cortex-M 调试和烧录工具。它通过 CMSIS-DAP、DAPLink、J-Link、ST-LINK 等调试探针访问目标芯片,支持下载程序、擦除 flash、复位目标板、GDB 调试服务和命令行交互。
本工程里的分工可以理解为:
text
CMake 读取工程配置
-> Ninja 执行构建任务
-> arm-none-eabi-gcc 编译链接生成 aaaa.elf
-> pyOCD 通过 CMSIS-DAP 把 aaaa.elf 烧录进 STM32F407
检查命令:
bash
command -v cmake
command -v ninja
command -v arm-none-eabi-gcc
command -v pyocd
pyocd --version
本机已检测到:
text
/opt/st/stm32cubeclt_1.21.0/CMake/bin/cmake
/opt/st/stm32cubeclt_1.21.0/Ninja/bin/ninja
/opt/st/stm32cubeclt_1.21.0/GNU-tools-for-STM32/bin/arm-none-eabi-gcc
/home/sg/.local/bin/pyocd
pyOCD 0.44.1
3. 其他可选方案
本工程当前采用 CMake + Ninja + arm-none-eabi-gcc + pyOCD,这套方案适合在 Linux 命令行、脚本、CI 或 VS Code 环境中使用。除此之外,还有以下常见方案。
3.1 Makefile + arm-none-eabi-gcc
使用 make 直接管理编译规则,不使用 CMake。
特点:
- 优点:简单直接,依赖少,很多老工程和教程都使用 Makefile。
- 缺点:大型工程里维护源文件、头文件路径、编译选项和多配置构建会比较繁琐。
- 适合:工程结构简单、手写 Makefile、只需要命令行编译的场景。
典型命令:
bash
make
make clean
如果要烧录,仍然可以配合 pyOCD:
bash
pyocd flash -t stm32f407zgtx build/firmware.elf
3.2 STM32CubeIDE
ST 官方 Eclipse 系列 IDE,集成工程管理、编译、调试和烧录。
特点:
- 优点:图形界面完整,适合初学者;和 CubeMX 集成较好;对 ST-LINK 支持最好。
- 缺点:相对重,工程文件较多;自动生成配置较强,命令行自动化不如 CMake 直接。
- 适合:主要使用 ST-LINK、希望图形化调试、偏向官方 IDE 工作流的场景。
常见流程:
text
导入 .ioc 或 STM32 工程
-> Build
-> Debug/Run
-> 通过 ST-LINK 烧录和调试
注意:STM32CubeIDE 对 ST-LINK 支持最好。普通 CMSIS-DAP 是否能直接用于 CubeIDE 调试,取决于插件和调试后端配置,通常不如 pyOCD/OpenOCD 直接。
3.3 STM32CubeCLT
ST 官方命令行工具包,包含 CMake、Ninja、GNU Arm 工具链、STM32CubeProgrammer CLI 等。
本机使用的 CMake、Ninja 和 arm-none-eabi-gcc 就来自 STM32CubeCLT:
text
/opt/st/stm32cubeclt_1.21.0/
特点:
- 优点:官方提供,组件比较完整;适合 Linux 命令行和 CI。
- 缺点:STM32CubeProgrammer 的 SWD/JTAG 主要面向 ST-LINK/J-LINK 等支持的接口,普通 CMSIS-DAP 烧录 STM32 时不一定比 pyOCD 方便。
使用 STM32CubeProgrammer CLI 通过 ST-LINK 烧录的典型命令:
bash
STM32_Programmer_CLI -c port=SWD -w build/Debug/aaaa.elf -v -rst
如果使用的不是 ST-LINK,而是 CMSIS-DAP,本工程更推荐 pyOCD。
3.4 OpenOCD
OpenOCD 是常见的开源片上调试工具,支持多种调试器和芯片。
特点:
- 优点:生态成熟,GDB 调试常用;支持 CMSIS-DAP、ST-LINK、J-Link、FTDI 等多种接口。
- 缺点:配置文件组合较多,不同发行版自带版本可能偏旧;遇到具体探针兼容性时需要调试配置。
- 适合:需要 GDB server、自动化烧录、非 pyOCD 支持目标、复杂调试配置的场景。
如果系统安装了 OpenOCD,并且有对应配置文件,可用类似命令:
bash
openocd \
-f interface/cmsis-dap.cfg \
-f target/stm32f4x.cfg \
-c "program build/Debug/aaaa.elf verify reset exit"
本次机器上没有检测到 openocd 命令,所以本次没有采用该方案。
3.5 J-Link + JLinkExe/JFlash
如果使用 SEGGER J-Link 调试器,可以使用 SEGGER 官方工具。
特点:
- 优点:速度快、稳定性好、商业工具链支持广。
- 缺点:需要 J-Link 硬件;部分场景涉及授权要求。
- 适合:长期调试、量产测试、对烧录速度和稳定性要求较高的场景。
典型方式是写一个 J-Link command file,然后执行:
bash
JLinkExe -device STM32F407ZG -if SWD -speed 4000 -CommanderScript flash.jlink
示例 flash.jlink 内容:
text
connect
loadfile build/Debug/aaaa.elf
r
g
exit
3.6 ST-LINK + STM32CubeProgrammer
如果使用 ST-LINK/V2、ST-LINK/V3 或 Nucleo/Discovery 板载 ST-LINK,可以直接用 STM32CubeProgrammer。
特点:
- 优点:ST 官方支持,识别 STM32 最完整;图形界面和命令行都可用。
- 缺点:需要 ST-LINK 硬件;不适用于所有 CMSIS-DAP 探针。
命令行烧录:
bash
STM32_Programmer_CLI -c port=SWD freq=4000 -w build/Debug/aaaa.elf -v -rst
3.7 通过系统 Bootloader 烧录
STM32F407 内置系统 Bootloader,可通过 UART、USB DFU 等方式烧录,具体取决于 BOOT0/BOOT1 启动配置和芯片支持的接口。
特点:
- 优点:不需要 SWD 调试器,适合只做固件下载。
- 缺点:需要控制 BOOT0 进入系统 Bootloader;不能像 SWD 一样方便调试;接口和流程受硬件设计影响。
UART Bootloader 可配合 STM32CubeProgrammer:
bash
STM32_Programmer_CLI -c port=/dev/ttyUSB0 br=115200 -w build/Debug/aaaa.elf -v
USB DFU Bootloader 可用:
bash
STM32_Programmer_CLI -c port=USB1 -w build/Debug/aaaa.elf -v
也可以使用开源工具,例如 dfu-util,但需要先生成或转换成合适格式。
3.8 方案选择建议
本工程目前最合适的路线:
text
CMake + Ninja + arm-none-eabi-gcc + pyOCD + CMSIS-DAP
原因:
- 当前工程已经是 CMake 工程。
- 当前烧录器已经被识别为 CMSIS-DAP。
- pyOCD 安装 STM32F4 pack 后已经成功烧录。
- 全流程可以命令行自动化,适合反复编译和烧录。
如果以后更换硬件,可以按下面选择:
- 使用 CMSIS-DAP:优先 pyOCD,其次 OpenOCD。
- 使用 ST-LINK:优先 STM32CubeProgrammer 或 STM32CubeIDE,也可以用 OpenOCD。
- 使用 J-Link:优先 J-Link 官方工具,也可以用 pyOCD/OpenOCD。
- 没有调试器:考虑 STM32 系统 Bootloader,通过 UART 或 USB DFU 烧录。
4. 检查 USB 烧录器
查看 USB 设备:
bash
lsusb
能看到类似设备即可:
text
Bus 003 Device 002: ID 04d8:00df Microchip Technology, Inc. ATK-HS-V3-CMSIS-DAP
使用 pyOCD 查看探针:
bash
pyocd list
正常情况下会看到:
text
# Probe/Board Unique ID Target
-------------------------------------------------------
0 ATK ATK-HS-V3-CMSIS-DAP ATK 20190528 n/a
这里 Target 显示 n/a 不一定是错误。它表示 pyOCD 没有自动识别目标 MCU,后续烧录时手动指定 -t stm32f407zgtx 即可。
5. 确认工程 MCU 型号
查看 .ioc 文件中的 MCU 信息:
bash
rg -n "Mcu\\.CPN|Mcu\\.Name|Mcu\\.UserName|ProjectManager\\.DeviceId" aaaa.ioc
本工程结果:
text
Mcu.CPN=STM32F407ZGT6
Mcu.Name=STM32F407Z(E-G)Tx
Mcu.UserName=STM32F407ZGTx
ProjectManager.DeviceId=STM32F407ZGTx
所以 pyOCD target 应使用:
text
stm32f407zgtx
6. 编译工程
进入工程目录:
bash
cd /home/sg/aaaa
配置 CMake:
bash
cmake --preset Debug
编译:
bash
cmake --build --preset Debug
本次编译成功后的关键信息:
text
[22/22] Linking C executable aaaa.elf
Memory region Used Size Region Size %age Used
RAM: 1584 B 128 KB 1.21%
CCMRAM: 0 B 64 KB 0.00%
FLASH: 4820 B 1 MB 0.46%
检查产物:
bash
find build/Debug -maxdepth 2 -type f \( -name '*.elf' -o -name '*.hex' -o -name '*.bin' -o -name '*.map' \) -print
本工程生成:
text
build/Debug/aaaa.elf
build/Debug/aaaa.map
7. 安装 STM32F4 pyOCD 支持包
pyOCD 默认不一定内置所有 STM32 型号。本机最初执行:
bash
pyocd flash -t stm32f407zg /home/sg/aaaa/build/Debug/aaaa.elf
报错:
text
Target type stm32f407zg not recognized.
因此需要安装 STM32F4 的 DFP pack。
安装命令:
bash
pyocd pack install STM32F407ZG
第一次执行时,pyOCD 会先下载 pack 索引:
text
No pack index present, downloading now...
Downloading descriptors (1768/1768)
Downloading packs:
Keil.STM32F4xx_DFP.3.1.1
安装完成后查看已安装 pack:
bash
pyocd pack show
正常结果:
text
Pack Version
--------------------------------
Keil.STM32F4xx_DFP 3.1.1
查询 STM32F407 目标名称:
bash
pyocd list --targets | rg -i 'stm32f407zg|stm32f407'
能看到:
text
stm32f407zg STMicroelectronics STM32F407ZG STM32F4 Series, STM32F407 pack
stm32f407zgtx STMicroelectronics STM32F407ZGTx STM32F4 Series, STM32F407 pack
本工程使用 STM32F407ZGTx,所以烧录时使用:
text
-t stm32f407zgtx
8. 烧录固件
烧录当前 Debug ELF:
bash
pyocd flash -t stm32f407zgtx /home/sg/aaaa/build/Debug/aaaa.elf
本次成功输出:
text
Loading /home/sg/aaaa/build/Debug/aaaa.elf
Erasing...
Programming...
Erased 16384 bytes (1 sector), programmed 5120 bytes (5 pages), skipped 0 bytes (0 pages)
烧录完成后复位目标板:
bash
pyocd reset -t stm32f407zgtx
9. 全流程命令汇总
如果环境已经配置好、pack 已安装,可以直接执行:
bash
cd /home/sg/aaaa
cmake --preset Debug
cmake --build --preset Debug
pyocd flash -t stm32f407zgtx /home/sg/aaaa/build/Debug/aaaa.elf
pyocd reset -t stm32f407zgtx
如果是第一次在这台机器上烧录 STM32F407,需要先执行:
bash
pyocd pack install STM32F407ZG
完整首次流程:
bash
cd /home/sg/aaaa
# 检查工具
command -v cmake
command -v ninja
command -v arm-none-eabi-gcc
command -v pyocd
pyocd --version
# 检查 DAP
lsusb
pyocd list
# 安装 STM32F4 支持包
pyocd pack install STM32F407ZG
pyocd pack show
pyocd list --targets | rg -i 'stm32f407zg|stm32f407'
# 编译
cmake --preset Debug
cmake --build --preset Debug
# 烧录并复位
pyocd flash -t stm32f407zgtx /home/sg/aaaa/build/Debug/aaaa.elf
pyocd reset -t stm32f407zgtx
10. 常见问题
10.1 pyocd list 能看到 DAP,但 Target 是 n/a
这是常见现象。CMSIS-DAP 被识别了,但 pyOCD 没有自动识别目标芯片。
解决方式:烧录时手动指定 target。
bash
pyocd flash -t stm32f407zgtx /home/sg/aaaa/build/Debug/aaaa.elf
10.2 Target type ... not recognized
说明 pyOCD 没有对应芯片支持包。
安装 pack:
bash
pyocd pack install STM32F407ZG
然后确认:
bash
pyocd list --targets | rg -i 'stm32f407zg|stm32f407'
10.3 无法访问 USB 或需要权限
如果普通用户执行 pyocd list 或 lsusb 出现 USB 权限问题,可以临时使用 sudo 测试:
bash
sudo pyocd list
sudo pyocd flash -t stm32f407zgtx /home/sg/aaaa/build/Debug/aaaa.elf
长期建议配置 udev 规则,让普通用户可以访问 CMSIS-DAP。
10.4 连接目标失败
检查以下项目:
- 目标板是否供电。
- DAP 和目标板是否共地。
SWDIO和SWCLK是否接反。- 是否连接了目标板 3.3V 到 DAP 的
VTref。 - 目标芯片是否被其他调试器占用。
- 尝试降低 SWD 频率:
bash
pyocd flash -t stm32f407zgtx --frequency 1000000 /home/sg/aaaa/build/Debug/aaaa.elf
10.5 编译失败
先确认 CMake preset 是否存在:
bash
cmake --list-presets
再重新配置和编译:
bash
cmake --preset Debug
cmake --build --preset Debug
如果工具链找不到,检查 STM32CubeCLT 或 arm-none-eabi-gcc 是否安装并加入 PATH。
11. 本次实际执行记录
本次执行过的关键命令:
bash
cd /home/sg/aaaa
cmake --preset Debug
cmake --build --preset Debug
lsusb
pyocd list
pyocd pack install STM32F407ZG
pyocd pack show
pyocd list --targets | rg -i 'stm32f407zg|stm32f407'
pyocd flash -t stm32f407zgtx /home/sg/aaaa/build/Debug/aaaa.elf
pyocd reset -t stm32f407zgtx
最终结果:
text
编译成功。
烧录成功。
已擦除 16384 bytes。
已写入 5120 bytes。
目标板已复位。