feat(pack): v2 双固件 profile 打包 — fw_pack 公共库 + CLI 重构 + GUI 打包弹窗

This commit is contained in:
2026-10-22 00:53:52 +08:00
parent d776979a5a
commit 031ee4efdf
12 changed files with 2345 additions and 292 deletions
+39 -15
View File
@@ -1,8 +1,9 @@
# DAPLink Flash — GD32 固件烧录 · 补齐 · 镜像拼接
# DAPLink Flash — GD32 固件烧录 · 双固件打包 · 补齐 · 拼接
> GD32E230 系列的桌面烧录/固件处理工具:**OpenOCD 烧录**(DAPLink / GD-Link /
> ST-Link / J-Link)+ **补齐 Pad**(Y-Modem 页对齐)+ **拼接 Merge**
> (Bootloader + APP + 有效标志 → 整片镜像)。
> 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`
@@ -10,7 +11,7 @@
> - **要改代码/重新打包**:见 §5、§6。
>
> 界面与构建方式对齐 DLPilot 项目(CustomTkinter 深色卡片仪表盘 +
> PyInstaller onefile + Gitea Release 发布)。更新:2026-09-14
> PyInstaller onedir + Gitea Release 发布)。更新:2026-10-22
## 1. 功能总览
@@ -20,10 +21,11 @@
| 固件格式 | 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 / --pad / --merge ...`,见 §4) |
| 命令行模式 | 全部功能可脚本化调用(`--flash / --pack / --pad / --merge ...`,见 §4) |
| 外观 | 跟随系统深/浅色,顶栏可切换 Dark / Light / System |
## 2. 下载与安装
@@ -54,15 +56,15 @@ DAPLinkFlash/
## 3. GUI 使用
主窗口为单列仪表盘,补齐/拼接经顶栏按钮弹出独立窗口:
主窗口为单列仪表盘,打包/补齐/拼接经顶栏按钮弹出独立窗口:
```
顶栏 DAPLink Flash [补齐 (Pad)] [拼接 (Merge)] 关于 Dark/Light/System
顶栏 DAPLink Flash [打包 (v2)] [补齐 (Pad)] [拼接 (Merge)] 关于 Dark/Light/System
┌ 探针与工具链 [自动定位] ┐
├ 芯片与固件(型号/固件/基地址) ┤
├ 运行日志 — OpenOCD 输出 ┤
├ 运行日志 — OpenOCD 输出 / 打包校验 ┤
└ 操作: 检测/烧录/擦除/读取/复位/停止 ┘
弹窗 补齐 (Pad) / 拼接 (Merge) — 非模态, 配置与主窗口共享
弹窗 打包 (v2) / 补齐 (Pad) / 拼接 (Merge) — 非模态, 配置与主窗口共享
```
1. **选工具链**:默认自动定位(内置 → 本机 `D:/toolchain` → PATH),左卡右上
@@ -76,12 +78,16 @@ DAPLinkFlash/
单独 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`,整片镜像),地址按典型布局
预填,点"执行拼接"。
典型布局:`0x08000000` Bootloader 8KB | `0x08002000` APP | `0x0800FFFC`
有效标志 `0xEEEEEEEE` | `0x08010000` Flash 结束 (64KB)。
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` 在首次启动时自动迁移。
@@ -102,8 +108,11 @@ 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
--align N / --pad-byte 0xFF / -o OUT pad 参数
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 手动指定工具链(默认自动定位)
```
@@ -116,7 +125,7 @@ python src/flash_gui.py --merge bl.bin app.bin 拼接 → app_BL.bin
FlashTool/
├── src/ # 源代码(人工维护区)
│ ├── flash_gui.py # 入口与命令行模式(argparse 分发)
│ ├── app_gui.py # CustomTkinter 主界面(双栏仪表盘)
│ ├── app_gui.py # CustomTkinter 主界面(单列仪表盘 + 打包/补齐/拼接弹窗)
│ ├── openocd_runner.py # 工具链定位 / OpenOCD 命令构建与子进程
│ ├── fw_image.py # 补齐(pad)/拼接(merge) + 芯片参数表
│ ├── config.py # 运行目录与 flash_gui_settings.json 配置
@@ -134,8 +143,13 @@ FlashTool/
从源码运行:`python src/flash_gui.py` 或双击 `start_flash_gui.bat`,
需 Python ≥3.10 + customtkinter(`py -m pip install customtkinter`);
OpenOCD 用本机安装(默认找 `D:/toolchain/openocd`)或先跑一次
`package_release.py` 把工具链放进 `release/toolchain/`。
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. 构建与发布
@@ -159,6 +173,16 @@ python publish_gitea.py DAPLinkFlash-v0.1.0-win64.zip --insecure
处理见 §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 旁边,只读目录存不了配置;