# DAPLink Flash — GD32 固件烧录 · 双固件打包 · 补齐 · 拼接 > GD32E230 系列的桌面烧录/固件处理工具:**OpenOCD 烧录**(DAPLink / GD-Link / > ST-Link / J-Link)+ **打包 v2**(双固件 profile 布局 → UPDATE / B / FULL 镜像 > + MD5 清单,与命令行工具共用 `fw_pack.py` 公共库)+ **补齐 Pad**(Y-Modem > 页对齐)+ **拼接 Merge**(Bootloader + APP + 有效标志 → 整片镜像)。 > > - **只想用工具**:到 [Gitea Releases](https://gitea.hulk.wang/hulk/gd32e230f8_firmware_merge_tool/releases) > 下载 `DAPLinkFlash-vX.Y.Z-win64.zip`,解压双击 `DAPLinkFlash.exe` > (Windows 10/11 x64,免安装、无需 Python,**内置 OpenOCD 工具链**)。 > - **要改代码/重新打包**:见 §5、§6。 > > 界面与构建方式对齐 DLPilot 项目(CustomTkinter 深色卡片仪表盘 + > PyInstaller onedir + Gitea Release 发布)。更新:2026-10-22 ## 1. 功能总览 | 功能 | 说明 | |---|---| | OpenOCD 烧录 | 检测设备 / 烧录固件 / 整片擦除 / 读取 Flash / 复位芯片 / 停止,OpenOCD 输出实时进日志区 | | 固件格式 | BIN / HEX / ELF——HEX/ELF 自动用文件内地址,仅 BIN 需填基地址(完整镜像 `0x08000000`,单独 APP `0x08002000`) | | 芯片型号 | GD32E230F4 / F6 / F8 / C8,自动带出 Flash 大小与 target 配置 | | 烧录器 | DAPLink / CMSIS-DAP、GD-Link、ST-Link、J-Link、CMSIS-DAP(TCP)、Custom;支持适配器速度与探针序列号 | | 打包 v2 | 双固件 profile 布局(默认 `ceramixnano_mb_v51`):A/B 包向量表自动识别、补页+trailer/满槽+记录、CRC-16/XMODEM、FULL 整片镜像、MD5 清单、写盘回读复核 | | 补齐 Pad | BIN 尾部补 `0xFF` 到 1K/2K/4K 页边界;bootloader 的 Y-Modem 只按 1K 整包写 Flash,最后一包不满必须先补齐 | | 拼接 Merge | Bootloader + APP + 有效标志(`0xEEEEEEEE` @`0x0800FFFC`) → 整片 Flash 镜像,逻辑与 `merge_bin.py` 一致 | | 内置工具链 | 发布包自带 OpenOCD(`toolchain/openocd/`),GUI 自动定位,免安装免配置 | | 命令行模式 | 全部功能可脚本化调用(`--flash / --pack / --pad / --merge ...`,见 §4) | | 外观 | 跟随系统深/浅色,顶栏可切换 Dark / Light / System | ## 2. 下载与安装 1. 打开 [Releases 页面](https://gitea.hulk.wang/hulk/gd32e230f8_firmware_merge_tool/releases), 取最新的 `DAPLinkFlash-vX.Y.Z-win64.zip`; 2. 解压到**任意可写目录**(配置 `flash_gui_settings.json` 写在 exe 旁边); 3. 进入解压出的 `DAPLinkFlash` 文件夹,双击 `DAPLinkFlash.exe`。 目录版(onedir)无临时解压等待,启动接近秒开。 包内包含: ``` DAPLinkFlash/ ├── DAPLinkFlash.exe 主程序(启动器) ├── _internal/ 运行库(PyInstaller onedir, 须与 exe 同目录) ├── toolchain/openocd/ 内置 OpenOCD(GUI 自动定位) │ ├── bin/openocd.exe + libftdi1.dll / libusb-1.0.dll │ └── openocd/scripts/ interface / target 配置脚本 └── README.md 本说明 ``` > **SmartScreen 拦截("Windows 已保护你的电脑")**:exe 未做代码签名, > 浏览器下载的压缩包带"来自网络"标记。任选其一绕过: > ① 点"更多信息 → 仍要运行"(每台电脑每个文件仅一次); > ② 下载后**先右键 zip → 属性 → 勾选"解除锁定"→ 确定**,再解压,包内所有文件都不会再拦; > ③ 用 7-Zip / WinRAR 解压(不继承网络标记)。 ## 3. GUI 使用 主窗口为单列仪表盘,打包/补齐/拼接经顶栏按钮弹出独立窗口: ``` 顶栏 DAPLink Flash [打包 (v2)] [补齐 (Pad)] [拼接 (Merge)] 关于 Dark/Light/System ┌ 探针与工具链 [自动定位] ┐ ├ 芯片与固件(型号/固件/基地址) ┤ ├ 运行日志 — OpenOCD 输出 / 打包校验 ┤ └ 操作: 检测/烧录/擦除/读取/复位/停止 ┘ 弹窗 打包 (v2) / 补齐 (Pad) / 拼接 (Merge) — 非模态, 配置与主窗口共享 ``` 1. **选工具链**:默认自动定位(内置 → 本机 `D:/toolchain` → PATH),左卡右上 "自动定位"可重新探测;也可手动浏览指定 `openocd.exe` 与 scripts 目录; 2. **选芯片与烧录器**:芯片型号下拉自动带出 Flash 大小和 target;烧录器下拉 自动带出 interface cfg;多探针时填序列号; **自定义 cfg**:把自己的 OpenOCD cfg 文件(如工程定制的 target 配置)放进 程序旁的 `cfgs/` 目录,"Target 配置"/"Interface 配置"下拉框即列出 `cfgs/<文件名>` 供选用;`cfgs/` 会随发布包分发; 3. **选固件**:点"浏览"选 BIN/HEX/ELF;BIN 确认基地址(完整镜像 `0x08000000`, 单独 APP `0x08002000`); 4. **点"检测设备"**确认链路通 → **点"烧录固件"**;输出实时显示在右下日志区; 5. **固件工具**(顶栏按钮弹出的独立窗口,非模态): - 打包 v2:选 profile(内置下拉或浏览 JSON)+ BL/A 包/B 包 bin(至少一个)+ 输出目录,点"执行打包"→ `*_UPDATE.bin` / `*_B.bin` / `*_FULL.bin` + MD5 清单; A/B 槽按向量表自动校验,逐项字节校验与回读复核结果流进主日志; - 补齐:选输入 BIN 后输出名自动带出(`*_update.bin`,Y-Modem 升级包),对齐默认 1K,点"执行补齐"; - 拼接:选 Bootloader 与 APP 后输出名自动带出(`*_BL.bin`,整片镜像),地址按典型布局 预填,点"执行拼接"。 v2 双固件布局(默认 profile `ceramixnano_mb_v51`)与打包规则详见仓库根 [README.md](../README.md);legacy 单槽布局:`0x08000000` Bootloader 8KB | `0x08002000` APP | `0x0800FFFC` 有效标志 `0xEEEEEEEE`。 配置(全部输入框的值)自动保存在 exe 旁的 `flash_gui_settings.json`,下次启动 自动恢复;旧版 `config/flash_gui_<主机名>.json` 在首次启动时自动迁移。 ## 4. 命令行模式 exe 版无控制台,脚本化请用源码方式(或 `build_exe.py --debug` 打的带控制台变体): ``` python src/flash_gui.py 启动 GUI python src/flash_gui.py --seconds 5 GUI 5 秒自动关闭(冒烟测试) python src/flash_gui.py --version 打印 OpenOCD 版本(验证工具链定位) python src/flash_gui.py --detect 检测烧录器与目标芯片 python src/flash_gui.py --flash app.bin 烧录(BIN 默认基地址 0x08000000) python src/flash_gui.py --flash app.bin --base 0x08002000 --no-reset python src/flash_gui.py --erase 整片擦除 python src/flash_gui.py --read dump.bin 读取整片 Flash python src/flash_gui.py --reset 复位运行 python src/flash_gui.py --pad app.bin 补齐到 1K → app_pad.bin python src/flash_gui.py --merge bl.bin app.bin 拼接 → app_BL.bin python src/flash_gui.py --pack a.bin b.bin --pack-bl bl.bin -o outdir v2 双固件打包 → UPDATE/B/FULL+MD5 --align N / --pad-byte 0xFF / -o OUT pad 参数(-o 对 pack 为目录) --app-addr / --flag-addr / --flash-size / --flag-value merge 参数 --pack-profile ceramixnano_mb_v51|JSON / --pack-no-full pack 参数 --speed 4000 / --serial SN / --interface cfg / --target cfg --openocd PATH / --scripts DIR 手动指定工具链(默认自动定位) ``` 退出码:OpenOCD 操作非 0 即失败,可直接用于 CI/脚本串联。 ## 5. 目录结构与从源码运行 ``` FlashTool/ ├── src/ # 源代码(人工维护区) │ ├── flash_gui.py # 入口与命令行模式(argparse 分发) │ ├── app_gui.py # CustomTkinter 主界面(单列仪表盘 + 打包/补齐/拼接弹窗) │ ├── openocd_runner.py # 工具链定位 / OpenOCD 命令构建与子进程 │ ├── fw_image.py # 补齐(pad)/拼接(merge) + 芯片参数表 │ ├── config.py # 运行目录与 flash_gui_settings.json 配置 │ ├── build_exe.py # PyInstaller 打包 → release/ │ ├── package_release.py # 组装发布 zip(exe + 内置 OpenOCD 工具链) │ ├── publish_gitea.py # 上传到 Gitea Release │ └── logos/ # 图标源(make_ico.py + png/ico) ├── release/ # 构建与发布产物(机器生成区, 不手改/不入库) │ ├── DAPLinkFlash/ # onedir 程序目录: exe + _internal/ + toolchain/ │ └── *.zip # 发布包(上传 Gitea Release) ├── toolchain/openocd/ # (可选) vendor 进仓库的工具链, 不入库 ├── start_flash_gui.bat # 源码模式双击启动器 └── README.md # 本说明 ``` 从源码运行:`python src/flash_gui.py` 或双击 `start_flash_gui.bat`, 需 Python ≥3.10 + customtkinter(`py -m pip install customtkinter`); OpenOCD 默认找本机 `D:/toolchain/openocd`,要 vendor 的话把工具链放到 `FlashTool/toolchain/openocd/`(`package_release.py` 打包时同样优先取这里)。 > **fw_pack.py**(v2 打包公共库)位于**仓库根目录**(与命令行工具共用,单一真相): > 源码模式由 `app_gui.py`/`flash_gui.py` 自动把仓库根补进 `sys.path`; > PyInstaller 打包由 `build_exe.py` 的 `--paths 仓库根 --hiddenimport fw_pack` > 收进运行库,不要把副本复制进 `src/`。 ## 6. 构建与发布 ```powershell cd src python logos/make_ico.py # (可选) 改图标后重新生成 png/ico, 需 Pillow python build_exe.py # 打包 → ../release/DAPLinkFlash/(onedir 目录版, # 启动秒开; 自动装 PyInstaller, CTk 主题数据自动收集) python build_exe.py --debug # 额外出一个带控制台的调试变体(命令行模式可见输出) python package_release.py 0.1.0 # 组装 release/DAPLinkFlash-v0.1.0-win64.zip # 含内置 OpenOCD 工具链(来源见脚本说明) python publish_gitea.py DAPLinkFlash-v0.1.0-win64.zip --insecure # 上传 Gitea Release(需环境变量 GITEA_TOKEN) ``` 版本号默认从最近的 `DAPLinkFlash-v*` git tag 推断,无 tag 时手动指定。 ## 7. 注意事项 / FAQ - **"Windows 已保护你的电脑"(SmartScreen)**:exe 无代码签名所致, 处理见 §2 的三种绕过方式;要彻底消除需购买代码签名证书对 exe 签名; - **"找不到 OpenOCD"**:点"自动定位";发布包用户确认解压后 `toolchain/openocd/` 目录和 exe 在一起; - **`Error connecting DP: cannot read IDR`(SWD 完全连不上)**:目标板对 SWD 无应答,与工具/命令无关,按序排查: ① 目标板是否已上电(DAPLink 指示灯亮 ≠ 板子有电,两者供电独立); ② DAPLink 的 **RST 引脚必须接到 GD32 的 NRST**——本类工程固件运行后会把 SWD 引脚复用为 LED,必须"按住复位连接"(内置 `cfgs/openocd_gdlink_gd32e23x.cfg` 已配置 `connect_assert_srst`),RST 线没接/松脱时就是这个错; ③ 拔插 DAPLink 的 USB、目标板彻底断电再上电(深睡/锁死状态恢复); ④ 速度降到 1000 kHz; ⑤ 确认运行的是 `DAPLinkFlash` 文件夹里的 exe(日志第一屏工具链应显示"内置", OpenOCD 版本 0.11.0-3、target 为 `cfgs/...` 才是新版); - **烧录失败排查**:①"检测设备"先验链路;② 探针序列号留空可排除序列号问题; ③ 速度过高可降到 1000 kHz;④ DAPLink 固件过旧换 GD-Link 固件试试; - **exe 放只读目录**:`flash_gui_settings.json` 写在 exe 旁边,只读目录存不了配置; - **重新打包后图标没变**:Windows 图标缓存,`ie4uinit -show` 或改个名即可; - **残留进程**:修改源码重新打包前先结束残留的 DAPLinkFlash 进程 (`build_exe.py` 会自动 taskkill); - **配置互不影响**:exe 与源码脚本各自按所在目录保存 `flash_gui_settings.json`。