# 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_v51`,GD32E230F8/64K) ```text 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 └──────────────────┘ ``` ### 计算规则(与 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` 文件夹 双击 `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](FlashTool/README.md)。 ## legacy 单槽模式(过渡兼容) 旧单槽方案(LDC1612 等,布局:BL 8K + APP 54K + 校准页 1K + 标志页 1K), `-f`/`-m` 触发: ```bash 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](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 FULL.bin 0x08000000; reset; exit" # J-Link JFlash -openprj project.jflash -open FULL.bin,0x08000000 -auto -exit ``` ## License MIT