Ubuntu 22.04 下使用 CMSIS-DAP 编译和烧录 STM32

本文记录本工程在 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.txtCMakePresets.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 命令,所以本次没有采用该方案。

如果使用 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

如果使用 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 listlsusb 出现 USB 权限问题,可以临时使用 sudo 测试:

bash 复制代码
sudo pyocd list
sudo pyocd flash -t stm32f407zgtx /home/sg/aaaa/build/Debug/aaaa.elf

长期建议配置 udev 规则,让普通用户可以访问 CMSIS-DAP。

10.4 连接目标失败

检查以下项目:

  • 目标板是否供电。
  • DAP 和目标板是否共地。
  • SWDIOSWCLK 是否接反。
  • 是否连接了目标板 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。
目标板已复位。
相关推荐
Junsir大斗师1 小时前
rocky9.7搭建grafana+loki+prometheus+alloy+node_exporter运维监控平台
linux·运维·grafana·prometheus
小此方1 小时前
Re:Mysql数据库基础篇(一):CentOS/Linux 环境下的完整安装/运行/登录Mysql流程与首次登录异常处理
linux·数据库·mysql
再玩一会儿看代码2 小时前
Java浅拷贝和深拷贝理解笔记
java·linux·开发语言·笔记·python·学习
草莓熊Lotso2 小时前
【Linux网络】深入理解 HTTP 协议(三):静态资源服务、状态码与重定向实战
linux·运维·服务器·网络·c++·http
hj2862512 小时前
Linux + 计算机网络全套精炼整理笔记
linux·运维
剑神一笑2 小时前
Linux chmod 命令深度解析:从权限位到符号模式的完整指南
linux·运维·chrome
流浪0012 小时前
LInux系统篇(二):深入剖析 Linux 进程:状态变迁、优先级及调度切换逻辑
linux·运维·服务器
daad7772 小时前
记录一个串口模块没有回包的问题
linux·运维·服务器
开发者联盟league2 小时前
在ubuntu上使用apt方式安装gitlab
linux·ubuntu·gitlab