hulk 8af9264ae4 chore: 内部迭代号出清收尾——CLI/测试/README 注释标签改中性表述,删除旧 profile 名迁移映射
- gd32e230_firmware_tool.py / test_fw_pack.py / README.md:v5/dev_fact 等会话自管理标签改为"双固件 bootloader"中性表述;参考产物 *_UPDATE_V5.bin 更名 *_UPDATE.bin(含验收包内 1.0.18),测试引用同步
- config.py:删除 _RENAMED_PROFILE 旧名迁移映射(ceramixnano_mb_v51 仅存在数小时;残留旧名加载 profile 时报错提示重选)
- AGENTS.md:留档出清进度,并修正"GUI 旧配置自动迁移"的过时表述(迁移映射已删)
- 55 项回归全绿;fw_pack.py 侧标签清理已随 5a85f68 入库
2026-10-25 00:43:53 +08:00

GD32E230 固件工具

本仓库提供 GD32E230 系列固件的打包与烧录工具:

  • 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(保留兼容)。

v2 双固件打包

布局(默认 profile CeramixNano_MB_Dual_FW,GD32E230F8/64K)

0x08000000  ┌──────────────────┐
            │     Bootloader   │  8K   页 0~7
0x08002000  ├──────────────────┤
            │   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 标志    │  1K   页 63      @0x0800FFFC
0x08010000  └──────────────────┘

计算规则(与双固件 bootloader 逐字一致)

  • 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 标志。

快速开始

# 全产物: A 包 → *_UPDATE.bin, 整片 → *_FULL.bin, 工厂镜像 → *_FACTORY.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 --no-full --no-factory

# 只打工厂烧录镜像(BL + B 满槽 + flag, 上电跳 B, 后续 OTA 写 A)
python gd32e230_firmware_tool.py app_b.bin -b bootloader.bin

输入 bin 从向量表自动识别 A/B 包(初始 SP 须在 SRAM [0x20000000,0x20002000]、 复位向量 Thumb 且落在对应槽区间);也可 --a/--b 显式指定,与向量表判定冲突时报错。 写盘后回读复核(重算 trailer/记录/锚点一致才报成功),并输出布局摘要与逐项字节校验 (FULL 19 项 / FACTORY 12 项)。

产物

产物 用途
*_UPDATE.bin A 包(补页+trailer),Ymodem/OTA 推送
*_FULL.bin 整片镜像(BL + A + B + flag),@0x08000000 烧录后直接运行 A(开发/验收底包)
*_FACTORY.bin 工厂烧录镜像(BL + B 满槽 + flag,无 A 内容、锚点擦除态),上电判定链落 B 跳出厂固件,之后 OTA 写 A
*.md5.txt 全部产物 MD5 清单 + 布局摘要(挂在 FULL,无 FULL 挂 FACTORY)

命名从输入文件名推导:FULL 为 <项目>_FULL_A-V<版本>_B-V<版本>[_日期].bin, FACTORY 为 <项目>_FACTORY_B-V<版本>[_日期].bin。不再单独输出 B 包文件 (B 内容已包含在 FULL/FACTORY 中)。

布局 profile(可复用到任意工程)

内置 CeramixNano_MB_Dual_FW(默认)与 f8_single_slot(无保底槽)。其他工程写一份 JSON 即可(保底槽 8K/28K、无保底槽、BL 更大等都支持),工具做完整性校验 (分区不重叠、页对齐、总和=flash_size):

{
  "profile": "CeramixNano_MB_Dual_FW",
  "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"
}
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_Dual_FW 内置名或 profile JSON 路径
-o, --output 输入所在目录 输出目录(产物自动命名)
--no-full — 不拼 FULL 整片镜像
--no-factory — 不出 FACTORY 工厂镜像

回归测试

python test_fw_pack.py     # 55 项: 规格基准 + 边界 + 篡改检测 + CLI 冒烟

覆盖 UPGRADE_PLAN_v2.md 第五节全部基准(CeramixNano 1.0.17/1.0.18/V1.0.12 实测值逐字节复现、恰整页/余量<4 扩页等);真机固件不在本仓库时相关用例自动跳过。

日常烧录优先使用图形界面工具,不需要打开 VSCode,也不需要记忆 OpenOCD 命令。 v2.6.0 起顶栏新增**"打包 (v2)"**弹窗(profile 选择 + BL/A/B 输入 + 输出目录), 与命令行共用 fw_pack.py,结果与逐项校验流进主日志。

  • 免安装版:到 Gitea Releases 下载 DAPLinkFlash-vX.Y.Z-win64.zip,解压后进入 DAPLinkFlash 文件夹 双击 DAPLinkFlash.exe 即可,包内自带 OpenOCD 工具链 (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。

legacy 单槽模式(过渡兼容)

旧单槽方案(LDC1612 等,布局:BL 8K + APP 54K + 校准页 1K + 标志页 1K), -f/-m 触发:

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 — 合成完整 Flash 镜像(不补齐)
-f, --fill — 补齐到整页边界(纯 0xFF)
-s, --flash-size F8 芯片型号:F4(16K) F6(32K) F8(64K)
-b, --bootloader 内置 gd32e230f8_bootloader_hulk.bin Bootloader .bin 路径
-o, --output 自动生成 输出文件路径
-a, --app-addr 0x08002000 APP 落位地址(1K 页对齐)

-m 与 -f 互斥;新工程请用 v2 模式(不带 -f/-m)。

旧版脚本

merge_bin.py / fill_bin.py 为旧版命令行脚本,功能已合并进 gd32e230_firmware_tool.py, 历史说明见 README_old.md。带 trailer 的临时打包脚本 已在 v2 落地后删除(能力并入 fw_pack.py)。

烧录

# OpenOCD
openocd -f interface/cmsis-dap.cfg -f target/gd32e23x.cfg \
  -c "init; reset halt; flash write_image erase FULL.bin 0x08000000; reset; exit"

# J-Link
JFlash -openprj project.jflash -open FULL.bin,0x08000000 -auto -exit

License

MIT

S
Description
这是一个用于GD32E230F8芯片的APP和BL合并的一个工具
Readme
385 KiB
Languages
Python 99.8%
Batchfile 0.2%