feat(pack): v2 双固件 profile 打包 — fw_pack 公共库 + CLI 重构 + GUI 打包弹窗
This commit is contained in:
@@ -1,34 +1,126 @@
|
||||
# GD32E230 固件工具
|
||||
|
||||
本仓库提供 GD32E230 系列固件的处理与烧录工具:
|
||||
本仓库提供 GD32E230 系列固件的打包与烧录工具:
|
||||
|
||||
- **DAPLink Flash GUI(推荐)**:图形界面烧录工具,位于 `FlashTool/`
|
||||
- **命令行固件工具**:`gd32e230_firmware_tool.py`(合成 + 补齐二合一)
|
||||
- **旧版脚本**:`merge_bin.py`、`fill_bin.py`(保留兼容)
|
||||
- **v2 双固件打包(默认)**:`gd32e230_firmware_tool.py` + `fw_pack.py` 公共库——
|
||||
布局 profile 化,输入编译好的 bin 自动识别 A/B 槽,产出 OTA 包 / B 底包 /
|
||||
整片镜像 + MD5 清单,写盘后回读复核;
|
||||
- **DAPLink Flash GUI(推荐)**:图形界面烧录工具(含 v2 打包弹窗),位于 `FlashTool/`;
|
||||
- **legacy 单槽模式(过渡兼容)**:`-f` 纯 0xFF 补页 / `-m` 拼 BL+APP+flag;
|
||||
- **旧版脚本**:`merge_bin.py`、`fill_bin.py`(保留兼容)。
|
||||
|
||||
## Flash 布局
|
||||
## v2 双固件打包
|
||||
|
||||
### 布局(默认 profile `ceramixnano_mb_v51`,GD32E230F8/64K)
|
||||
|
||||
```text
|
||||
0x08000000 ┌──────────────────┐
|
||||
│ Bootloader │ 8KB
|
||||
│ Bootloader │ 8K 页 0~7
|
||||
0x08002000 ├──────────────────┤
|
||||
│ │
|
||||
│ Application │ 最大 54KB (F8) / 22KB (F6) / 6KB (F4)
|
||||
│ │
|
||||
0x0800F800 ├──────────────────┤
|
||||
│ 校准数据 │ 1KB (预留)
|
||||
│ FW_A 运行槽 │ 36K 页 8~43 OTA/Ymodem 唯一接收区
|
||||
0x0800AFFC │ [槽尾锚点]──────│ ← 与 trailer 同值 {页数16|CRC16}
|
||||
0x0800B000 ├──────────────────┤
|
||||
│ FW_B 出厂保底槽 │ 19K 页 44~62 固定满槽,产线冻结
|
||||
0x0800FBF8 │ [B 记录 8B]─────│ ← magic|页数|CRC|2B 保留
|
||||
0x0800FC00 ├──────────────────┤
|
||||
│ 0xEEEE 标志 │ 1KB
|
||||
│ 0xEEEE 标志 │ 1K 页 63 @0x0800FFFC
|
||||
0x08010000 └──────────────────┘
|
||||
```
|
||||
|
||||
- 空白区域填充 `0xFF`(Flash 擦除默认值)
|
||||
- 标志位 `0xEEEE` 告诉 Bootloader:APP 有效,直接跳转
|
||||
- 校准页当前为预留空间
|
||||
### 计算规则(与 BL dev_fact v5.1 逐字一致)
|
||||
|
||||
- **CRC-16/XMODEM**(poly 0x1021、init 0x0000、不反转、无 xorout),
|
||||
启动自检向量 `"123456789" → 0x31C3`;
|
||||
- **A 包**:补 `0xFF` 至整 N 页,末 4B 写 trailer `{页数N(低16)|CRC(高16)}`;
|
||||
CRC 范围 = N 页内容去掉末 4B(含 0xFF 填充)。**整页扩展**:body 恰为整页
|
||||
倍数、或余量 < 4B → 向后扩 1 页;扩展后须 ≤ 槽容量,否则报错;
|
||||
- **B 包**:补 `0xFF` 恰好填满槽(19,456B),槽末 8B 写记录
|
||||
`{magic16=0xC0DE, 页数16, CRC16, 2B 0xFF}`;CRC 范围 = 槽内容去掉末 8B;
|
||||
**固件 > 槽-8B 直接报错**(固定槽不可扩展);
|
||||
- **FULL**:BL + A 包 + 槽尾锚点 + 空隙 0xFF + B 满槽 + `0xEEEE` 标志。
|
||||
|
||||
### 快速开始
|
||||
|
||||
```bash
|
||||
# 全产物: A 包 → *_UPDATE.bin, B 包 → *_B.bin, 整片 → *_FULL.bin + *.md5.txt
|
||||
python gd32e230_firmware_tool.py app_a.bin app_b.bin -b bootloader.bin
|
||||
|
||||
# 只打 A 包(OTA 升级包)
|
||||
python gd32e230_firmware_tool.py app_a.bin
|
||||
|
||||
# 仅 B 底包(产线备用,不拼 FULL)
|
||||
python gd32e230_firmware_tool.py app_b.bin
|
||||
```
|
||||
|
||||
输入 bin 从**向量表自动识别** A/B 包(初始 SP 须在 SRAM `[0x20000000,0x20002000]`、
|
||||
复位向量 Thumb 且落在对应槽区间);也可 `--a`/`--b` 显式指定,与向量表判定冲突时报错。
|
||||
写盘后回读复核(重算 trailer/记录/锚点一致才报成功),并输出布局摘要 + 19 项字节校验。
|
||||
|
||||
### 产物
|
||||
|
||||
| 产物 | 用途 |
|
||||
|---|---|
|
||||
| `*_UPDATE.bin` | A 包(补页+trailer),Ymodem/OTA 推送 |
|
||||
| `*_B.bin` | B 底包(满槽+记录),产线单独烧 B 槽备用 |
|
||||
| `*_FULL.bin` | 整片镜像,`@0x08000000` 整片烧录(底包) |
|
||||
| `*.md5.txt` | 全部产物 MD5 清单 + 布局摘要 |
|
||||
|
||||
FULL 镜像自动命名 `<项目>_FULL_A-V<版本>_B-V<版本>[_日期].bin`(从输入文件名推导)。
|
||||
|
||||
### 布局 profile(可复用到任意工程)
|
||||
|
||||
内置 `ceramixnano_mb_v51`(默认)与 `f8_single_slot`(无保底槽)。其他工程写一份
|
||||
JSON 即可(保底槽 8K/28K、无保底槽、BL 更大等都支持),工具做完整性校验
|
||||
(分区不重叠、页对齐、总和=flash_size):
|
||||
|
||||
```json
|
||||
{
|
||||
"profile": "ceramixnano_mb_v51",
|
||||
"chip": "GD32E230F8",
|
||||
"flash_base": "0x08000000",
|
||||
"flash_size": "64K",
|
||||
"page_size": 1024,
|
||||
"bl": { "addr": "0x08000000", "size": "8K" },
|
||||
"slot_a": { "addr": "0x08002000", "size": "36K",
|
||||
"anchor": "slot_end-4", "record": "{pages16@+0, crc16@+2}" },
|
||||
"slot_b": { "addr": "0x0800B000", "size": "19K", "fixed_slot": true,
|
||||
"record": "{magic16@+0=0xC0DE, pages16@+2, crc16@+4}",
|
||||
"record_addr": "slot_end-8" },
|
||||
"flag": { "page": "last", "addr": "0x0800FFFC", "value": "0xEEEE" },
|
||||
"crc": "xmodem"
|
||||
}
|
||||
```
|
||||
|
||||
```bash
|
||||
python gd32e230_firmware_tool.py app.bin --profile my_layout.json # 自定义布局
|
||||
python gd32e230_firmware_tool.py app.bin --profile f8_single_slot # 无保底槽
|
||||
```
|
||||
|
||||
### v2 参数
|
||||
|
||||
| 参数 | 默认值 | 说明 |
|
||||
|------|--------|------|
|
||||
| `bins...` | (可选) | 输入 bin,A/B 包按向量表自动识别 |
|
||||
| `--a BIN` / `--b BIN` | — | 显式指定 A/B 包(与自动识别冲突时报错) |
|
||||
| `-b, --bootloader` | — | BL bin(参与 FULL 拼接;缺省仅警告) |
|
||||
| `--profile` | `ceramixnano_mb_v51` | 内置名或 profile JSON 路径 |
|
||||
| `-o, --output` | 输入所在目录 | **输出目录**(产物自动命名) |
|
||||
| `--no-full` | — | 只出 UPDATE/B 包,不拼 FULL |
|
||||
|
||||
### 回归测试
|
||||
|
||||
```bash
|
||||
python test_fw_pack.py # 49 项: 规格基准 + 边界 + 篡改检测 + CLI 冒烟
|
||||
```
|
||||
|
||||
覆盖 UPGRADE_PLAN_v2.md 第五节全部基准(CeramixNano 1.0.17/1.0.18/V1.0.12
|
||||
实测值逐字节复现、恰整页/余量<4 扩页等);真机固件不在本仓库时相关用例自动跳过。
|
||||
|
||||
## DAPLink Flash GUI(推荐)
|
||||
|
||||
日常烧录优先使用图形界面工具,不需要打开 VSCode,也不需要记忆 OpenOCD 命令。
|
||||
v2.6.0 起顶栏新增**"打包 (v2)"**弹窗(profile 选择 + BL/A/B 输入 + 输出目录),
|
||||
与命令行共用 `fw_pack.py`,结果与逐项校验流进主日志。
|
||||
|
||||
- **免安装版**:到 [Gitea Releases](https://gitea.hulk.wang/hulk/gd32e230f8_firmware_merge_tool/releases)
|
||||
下载 `DAPLinkFlash-vX.Y.Z-win64.zip`,解压后进入 `DAPLinkFlash` 文件夹
|
||||
@@ -36,165 +128,50 @@
|
||||
(`toolchain/openocd/`),目标机器无需任何环境。
|
||||
- **源码运行**:`python FlashTool/src/flash_gui.py` 或双击 `FlashTool\start_flash_gui.bat`
|
||||
(需 Python 3.10+ 与 `pip install customtkinter`;OpenOCD 默认找 `D:/toolchain`)。
|
||||
- **命令行打包**:`python FlashTool/src/flash_gui.py --pack a.bin b.bin --pack-bl bl.bin -o outdir`
|
||||
|
||||
详细说明见 [FlashTool/README.md](FlashTool/README.md)(GUI 截图说明、命令行模式、
|
||||
构建与发布流程)。下面是旧单文件版说明保留的要点:
|
||||
详细说明见 [FlashTool/README.md](FlashTool/README.md)。
|
||||
|
||||
### 功能
|
||||
## legacy 单槽模式(过渡兼容)
|
||||
|
||||
- 烧录操作:检测设备、整片擦除、烧录固件、读取 Flash、复位芯片、停止
|
||||
- 固件格式:BIN / HEX / ELF
|
||||
- BIN:手动填写烧录基地址
|
||||
- HEX / ELF:自动使用文件内地址
|
||||
- 芯片型号:GD32E230F4 / F6 / F8 / C8,自动带出 Flash 大小和 target 配置
|
||||
- 烧录器:DAPLink / CMSIS-DAP、GD-Link、ST-Link、J-Link
|
||||
- 烧录参数:适配器速度、探针序列号、烧录前擦除、烧录后校验、烧录后复位运行
|
||||
- 固件处理:补齐(1K / 2K / 4K)、拼接 Bootloader + APP + 有效标志
|
||||
- 工具链自动定位:内置(exe 旁 `toolchain/openocd`)→ 本机 `D:/toolchain` → PATH
|
||||
|
||||
### 配置
|
||||
|
||||
- 配置文件:`flash_gui_settings.json`,保存在程序目录(exe 旁 / FlashTool 根),
|
||||
自动保存与恢复
|
||||
- 旧版 `config/flash_gui_<主机名>.json` 在新版首次启动时自动迁移
|
||||
|
||||
### 使用步骤
|
||||
|
||||
1. 连接烧录器(DAPLink / GD-Link 等)到目标板 SWD:SWDIO、SWCLK、GND
|
||||
2. 启动 GUI,选择芯片型号和烧录器型号
|
||||
3. 选择固件文件并确认地址:
|
||||
- 完整镜像(bootloader + app):`0x08000000`
|
||||
- 单独烧录 APP:`0x08002000`
|
||||
4. 点击“检测设备”确认连接正常
|
||||
5. 点击“烧录固件”
|
||||
|
||||
> Bootloader 的 Y-Modem 只按 1K 整包接收,OTA 升级包发送前请先用“补齐”功能处理。
|
||||
|
||||
## 命令行固件工具
|
||||
|
||||
### 快速开始
|
||||
旧单槽方案(LDC1612 等,布局:BL 8K + APP 54K + 校准页 1K + 标志页 1K),
|
||||
`-f`/`-m` 触发:
|
||||
|
||||
```bash
|
||||
# 合成完整镜像(整片烧录用)
|
||||
python gd32e230_firmware_tool.py -m app.bin
|
||||
|
||||
# 补齐升级包(Ymodem 升级用)
|
||||
python gd32e230_firmware_tool.py -f app.bin
|
||||
python gd32e230_firmware_tool.py -f app.bin # 纯 0xFF 补页, 无 trailer → *_UPDATE.bin
|
||||
python gd32e230_firmware_tool.py -m app.bin # BL+APP+0xEEEE → *_BL.bin
|
||||
python gd32e230_firmware_tool.py -m app.bin -s F6 # F6 芯片
|
||||
python gd32e230_firmware_tool.py -m app.bin -a 0x0800B000 -b bl.bin # FW_B 槽落位
|
||||
```
|
||||
|
||||
### 模式说明
|
||||
|
||||
#### `-m` / `--merge` — 合成完整镜像
|
||||
|
||||
将 Bootloader + APP + FLAG 合并为一个 Flash 镜像,直接整片烧录。**不补齐**(整片烧录无需考虑页对齐)。
|
||||
|
||||
```bash
|
||||
python gd32e230_firmware_tool.py -m CeramixNano-MB_V1.0.9.bin
|
||||
```
|
||||
|
||||
输出:`CeramixNano-MB_V1.0.9_BL.bin`
|
||||
|
||||
#### `-f` / `--fill` — 补齐升级包
|
||||
|
||||
将 APP 尾部补 `0xFF` 到 1KB 页边界,供 Bootloader 的 Ymodem 接收端使用。补齐后自动检查是否超过芯片 APP 容量上限。
|
||||
|
||||
```bash
|
||||
python gd32e230_firmware_tool.py -f CeramixNano-MB_V1.0.9.bin
|
||||
```
|
||||
|
||||
输出:`CeramixNano-MB_V1.0.9_UPDATE.bin`
|
||||
|
||||
### 参数
|
||||
|
||||
| 参数 | 默认值 | 说明 |
|
||||
|------|--------|------|
|
||||
| `app` | (必填) | APP 的 .bin 文件 |
|
||||
| `-m, --merge` | — | 合成完整 Flash 镜像 |
|
||||
| `-f, --fill` | — | 补齐到整页边界 |
|
||||
| `-m, --merge` | — | 合成完整 Flash 镜像(不补齐) |
|
||||
| `-f, --fill` | — | 补齐到整页边界(纯 0xFF) |
|
||||
| `-s, --flash-size` | `F8` | 芯片型号:`F4`(16K) `F6`(32K) `F8`(64K) |
|
||||
| `-b, --bootloader` | `gd32e230f8_bootloader_hulk.bin` | Bootloader .bin 路径 |
|
||||
| `-o, --output` | 自动生成 | 输出文件路径 |
|
||||
| `-h, --help` | — | 查看帮助 |
|
||||
| `-b, --bootloader` | 内置 `gd32e230f8_bootloader_hulk.bin` | Bootloader .bin 路径 |
|
||||
| `-o, --output` | 自动生成 | **输出文件**路径 |
|
||||
| `-a, --app-addr` | `0x08002000` | APP 落位地址(1K 页对齐) |
|
||||
|
||||
> **`-m` 和 `-f` 互斥**,每次只能选一种模式。
|
||||
|
||||
### 使用示例
|
||||
|
||||
```bash
|
||||
# F8 合成镜像(默认)
|
||||
python gd32e230_firmware_tool.py -m CeramixNano-MB_V1.0.9.bin
|
||||
|
||||
# F6 合成镜像
|
||||
python gd32e230_firmware_tool.py -m app.bin -s F6
|
||||
|
||||
# F8 补齐升级包(默认)
|
||||
python gd32e230_firmware_tool.py -f app.bin
|
||||
|
||||
# F4 补齐升级包
|
||||
python gd32e230_firmware_tool.py -f app.bin -s F4
|
||||
|
||||
# 自定义 Bootloader 和输出路径
|
||||
python gd32e230_firmware_tool.py -m app.bin -b my_bootloader.bin -o release.bin
|
||||
```
|
||||
|
||||
### 输出示例
|
||||
|
||||
**merge 模式:**
|
||||
|
||||
```text
|
||||
芯片: GD32E230F8 (64KB)
|
||||
|
||||
合成完成: CeramixNano-MB_V1.0.9_BL.bin
|
||||
芯片 : 64KB
|
||||
Bootloader : 3272B @ 0x08000000
|
||||
Application: 25600B @ 0x08002000
|
||||
Flag : 0xEEEE @ 0x0800FFFC
|
||||
校准预留 : 1KB @ 0x0800F800
|
||||
APP 剩余 : 29696B
|
||||
总大小 : 65536B (64KB)
|
||||
```
|
||||
|
||||
**fill 模式:**
|
||||
|
||||
```text
|
||||
芯片: GD32E230F8 (64KB)
|
||||
补齐完成: app_UPDATE.bin
|
||||
原始大小: 25000B
|
||||
页大小 : 1024B (1KB)
|
||||
补齐字节: 600B
|
||||
输出大小: 25600B
|
||||
APP 上限: 55296B (54KB) → 剩余 29696B
|
||||
```
|
||||
|
||||
**超限拦截:**
|
||||
|
||||
```text
|
||||
错误:APP (60000B / 58.6KB) 超过最大容量 (55296B / 54KB)
|
||||
芯片 64KB: 64KB - 8KB(BL) - 1KB(校准) - 1KB(Flag) = 54KB
|
||||
```
|
||||
> `-m` 与 `-f` 互斥;新工程请用 v2 模式(不带 `-f/-m`)。
|
||||
|
||||
### 旧版脚本
|
||||
|
||||
`merge_bin.py` / `fill_bin.py` 为旧版命令行脚本,功能已合并进 `gd32e230_firmware_tool.py`,历史说明见 [README_old.md](README_old.md)。
|
||||
`merge_bin.py` / `fill_bin.py` 为旧版命令行脚本,功能已合并进 `gd32e230_firmware_tool.py`,
|
||||
历史说明见 [README_old.md](README_old.md)。v5 格式临时脚本 `make_v5_update.py`
|
||||
已于 v2 落地后删除(能力并入 `fw_pack.py`)。
|
||||
|
||||
### 烧录
|
||||
|
||||
```bash
|
||||
# OpenOCD
|
||||
openocd -f interface/cmsis-dap.cfg -f target/gd32e23x.cfg \
|
||||
-c "init; reset halt; flash write_image erase merged.bin 0x08000000; reset; exit"
|
||||
-c "init; reset halt; flash write_image erase FULL.bin 0x08000000; reset; exit"
|
||||
|
||||
# J-Link
|
||||
JFlash -openprj project.jflash -open merged.bin,0x08000000 -auto -exit
|
||||
JFlash -openprj project.jflash -open FULL.bin,0x08000000 -auto -exit
|
||||
```
|
||||
|
||||
### 安全校验
|
||||
|
||||
- Bootloader 体积不超过 APP 起始偏移(8KB)
|
||||
- APP 大小不超过芯片可用空间
|
||||
- fill 模式补齐后再次校验容量上限
|
||||
- 芯片不支持自动检测,需通过 `-s` 手动指定
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
Reference in New Issue
Block a user