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
+108
View File
@@ -0,0 +1,108 @@
# gd32e230f8_firmware_merge_tool v2 升级计划(需求规格 / 提示词)
> 本文可直接作为 AI 辅助重构的提示词使用;也是本次彻底升级的需求基线。
> 背景仓库:本仓库(main 分支);配套 skill:hulk-mcu-firmware(SKILL.md + tool/ 缓存)。
> 首个目标工程:CeramixNano-MB(GD32E230F8/64K,双固件 v5.1 布局,BL 侧 dev_fact@512bf7a)。
---
## 一、背景与目标
现有 `gd32e230_firmware_tool.py` 是单槽时代的工具:布局硬编码(APP@0x08002000、标志页、校准页),只有两种模式(`-f` 纯 0xFF 补页、`-m` 拼 BL+APP+flag)。现已演进为**双固件方案**(BL + FW_A 运行槽 + FW_B 出厂保底槽 + 记录/CRC),临时脚本(`make_v5_update.py`、拼 FULL 的临时逻辑)散落各处,需要彻底整合升级。
**目标**:一个布局可配置、可复用到任意 GD32E230 工程(不同 Flash 型号、不同槽大小、可有/可无保底槽)的固件打包工具:输入编译好的 bin,自动识别槽位、补页、计算长度与 CRC、写记录/trailer/标志,产出完整可烧录镜像与 OTA 包。
## 二、现状与痛点
1. 布局硬编码(0x08002000/末页标志/校准页),换工程即失效;
2. 无 A/B 双槽概念,无 trailer/记录/CRC 计算;
3. 新增的 `-a/--app-addr` 只是补丁,无法描述 B 记录、锚点等;
4. GUI(FlashTool)拼接逻辑同样固定 0x08002000;
5. 临时脚本(make_v5_update.py 等)逻辑未固化,存在两套真相。
## 三、核心设计:布局 Profile
用 JSON 配置文件描述一个工程的 Flash 布局(CLI 也可覆盖单项)。示例(CeramixNano-MB v5.1):
```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"
}
```
**可复用性要求**:其他工程仅换 profile——例如保底槽 8K 或 28K、无保底槽(`slot_b: null`)、BL 更大等;所有地址/大小支持 `0x` 十六进制与 `K` 后缀;工具对 profile 做完整性校验(分区不重叠、页对齐、总和=flash_size)。
## 四、功能规格
### 4.1 输入与自动识别
- 输入为**编译好的 bin**:底包(LD/向量配置在 B 槽基址,如 0x0800B000)与升级包(配置在 A 槽基址,如 0x08002000)。
- 工具从**向量表自动识别**:初始 SP ∈ SRAM、复位向量落在哪个槽区间 → 判定该 bin 属于 A 包还是 B 包;与显式参数冲突时报错。
- BL bin(可选)、底包 bin(可选)作为输入项;BL 需校验 ≤ `bl.size`。
### 4.2 计算规则(与 BL dev_fact 侧逐字一致,不得偏离)
- **CRC-16/XMODEM**(poly 0x1021、init 0x0000、不反转、无 xorout;测试向量 `"123456789"` → `0x31C3`——工具启动自检)。
- **A 包(OTA/升级包)**:补 0xFF 至整 N 页,末 4B 写 trailer `{页数N(低16), CRC(高16)}`,CRC 范围 = **N 页内容去掉末 4B**(含 0xFF 填充)。
- **槽尾锚点**(FULL 镜像用):A 槽末 4B(`slot_a` 末)写与 trailer 同值——BL 收包后会独立算出同值交叉验证。
- **B 包(底包,固定槽)**:补 0xFF 至**恰好填满槽**(如 19,456B),槽末 8B 写记录 `{magic16, pages16, crc16, 2B 0xFF}`,CRC 范围 = 槽内容去掉末 8B。**若 B 固件 > 槽−8B → 报错拒绝**(固定槽不可向后扩展,这是与 A 包的本质区别)。
- **flag**:`0xEEEE` 写 `flag.addr`(FULL 镜像)。
### 4.3 整页扩展规则(重点)
对动态补页的 A 包:设记录长度 R(A=4B trailer),
- `余量 = N_pages*1024 − body_len`;
- 若 `body_len` 恰为整页倍数,或 `余量 < R` → **向后扩展一页**(N_pages+1,全 0xFF 补齐后写记录);
- 扩展后仍须 ≤ `slot_a.size`,否则报错。
(B 包为固定槽,不适用扩展,见 4.2;若未来某工程 B 也动态化,须在 profile 中用 `fixed_slot:false` 显式声明并用同一规则。)
### 4.4 产物
1. `*_FULL.bin`:整片镜像 = BL + FW_A(补页+trailer+锚点) + 空隙0xFF + FW_B(满槽+记录) + flag;输出布局摘要与 MD5 清单(`*.md5.txt`)。
2. `*_UPDATE.bin`:A 包(补页+trailer),供 Ymodem/OTA。
3. `*_B.bin`(可选):满槽 B 包单独输出(产线备用)。
4. 兼容模式:`--legacy` 产出旧格式(纯 0xFF 补页、无 trailer),过渡期用。
### 4.5 校验(打包前硬门槛)
- 向量表:SP ∈ [0x20000000, 0x20002000];复位向量 Thumb 且落在声明槽内;
- 尺寸:A 包 ≤ 槽;B 包 = 槽(含记录);BL ≤ `bl.size`;
- 写盘后**回读复核**(重算 CRC/trailer 一致才报成功);
- 输出布局摘要表(各分区起止/大小/页号/记录值)供人工核对。
## 五、回归基准(本项目实测值,重构后必须逐项复现)
| 用例 | 期望 |
|---|---|
| 1.0.17 原始 bin 19,580B | A 包 20 页/20,480B,trailer=锚点=`0xD30F0014` |
| 1.0.18 原始 bin 19,580B | A 包 20 页,trailer=`0x6F380014`(CRC 0x6F38) |
| V1.0.12 B bin 19,456B(尾部已含 magic) | B 记录 = `DE C0 13 00 6F 18 FF FF`(pages=19,CRC=0x186F) |
| FULL 镜像 65,536B | 17 项字节校验全过(分区内容/空隙 0xFF/记录/flag) |
| 恰整页用例(构造 body=20480B) | 扩展为 21 页,trailer pages=21 |
| 余量<4B 用例(body=20477B) | 扩展为 21 页 |
## 六、GUI 与配套同步
- FlashTool(DAPLinkFlash):拼接/补齐弹窗升级为 profile 选择 + 双槽模式,与新 CLI 共用同一打包模块(抽公共库 `fw_pack.py`,CLI 与 GUI 仅为壳);
- 本仓库 README 更新;`AGENTS.md` 进度同步;
- skill `hulk-mcu-firmware`:改开发仓库 → push Gitea → `python scripts/update_tool.py` 同步缓存,SKILL.md 流程描述同步改。
## 七、实施步骤建议
1. 抽公共库 `fw_pack.py`(profile 解析/校验/计算/复核),CLI 改造调用之,先跑通第五节回归基准;
2. 新增 `--profile`(默认内置 ceramixnano_mb_v51),保留 `--legacy`;
3. GUI 接入;
4. 文档/skill 同步、Gitea 发布。
---
## 八、提示词(可直接粘贴给 AI 会话)
"请重构 `gd32e230_firmware_tool.py`:按上文第三~五节实现布局 profile 化的双固件打包工具,抽公共库供 GUI 复用。所有 CRC/记录/补页/整页扩展规则必须与第四节逐字一致,并以第五节回归基准作为验收(构造测试 bin 跑通全部用例)。要求:纯标准库、Windows 兼容、输出布局摘要与 MD5 清单、打包后回读复核;保留 `--legacy` 兼容模式;不要动 `FlashTool/` 之外的无关文件;完成后更新 README 与 AGENTS.md。"