feat(pack): FACTORY 工厂镜像 + 内置 profile 改名 CeramixNano_MB_Dual_FW

This commit is contained in:
2026-10-22 05:14:58 +08:00
parent 0ffa671656
commit 0a4095150b
10 changed files with 350 additions and 114 deletions
+23 -17
View File
@@ -4,10 +4,10 @@ GD32E230 固件打包工具 v2 — 布局 profile 化双固件打包 (A/B 槽 +
================================================================
v2 模式(默认): 输入编译好的 APP bin, 自动识别 A/B 槽, 产出
*_UPDATE.bin A 槽 OTA/Ymodem 包 (整 N 页 + 末 4B trailer {页数16|CRC16})
*_B.bin B 槽底包 (固定满槽 + 槽末 8B 记录 {magic|页数|CRC|2B FF})
*_FULL.bin 整片镜像 (BL + A 包 + 槽尾锚点 + B 满槽 + 0xEEEE 标志)
*.md5.txt 产物 MD5 清单 + 布局摘要 (随 FULL 生成)
*_UPDATE.bin A 槽 OTA/Ymodem 包 (整 N 页 + 末 4B trailer {页数16|CRC16})
*_FULL.bin 整片镜像 (BL + A 包 + 槽尾锚点 + B 满槽 + 0xEEEE 标志)
*_FACTORY.bin 工厂烧录镜像 (BL + B 满槽 + flag, 无 A 内容; 上电跳 B)
*.md5.txt 产物 MD5 清单 + 布局摘要 (随主镜像生成)
打包规则与 BL (dev_fact v5.1) 逐字一致, 写盘后回读复核。计算与校验在
fw_pack.py 公共库 (FlashTool GUI 共用)。
@@ -15,7 +15,7 @@ legacy 模式(过渡期兼容, -f/-m 二选一时启用): 旧单槽方案
-f/--fill 纯 0xFF 补页, 无 trailer (旧 BL 的 Ymodem 升级包)
-m/--merge BL + APP + 0xEEEE 标志 拼整片镜像 (不补齐)
v2 Flash 布局(默认 profile ceramixnano_mb_v51, GD32E230F8/64K):
v2 Flash 布局(默认 profile CeramixNano_MB_Dual_FW, GD32E230F8/64K):
0x08000000 Bootloader 8K 页 0~7
0x08002000 FW_A 运行槽 36K 页 8~43 OTA 唯一接收区, 槽尾锚点@0x0800AFFC
0x0800B000 FW_B 保底槽 19K 页 44~62 固定满槽, B 记录@0x0800FBF8
@@ -33,7 +33,10 @@ import fw_pack
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, SCRIPT_DIR)
TOOL_VERSION = '2.0.0'
TOOL_VERSION = '2.1.0'
# 默认布局 profile (与 fw_pack.BUILTIN_PROFILES 键一致)
DEFAULT_PROFILE = 'CeramixNano_MB_Dual_FW'
# ═══════════════════════════════════════════════════════════
@@ -96,7 +99,8 @@ def run_v2(args):
return 2
fw_pack.pack_all(
args.profile, a_path, b_path=b_path, bl_path=args.bootloader,
out_dir=out_dir, make_full=not args.no_full)
out_dir=out_dir, make_full=not args.no_full,
make_factory=not args.no_factory)
except fw_pack.FwPackError as exc:
print(f'\n错误:{exc}', file=sys.stderr)
return 1
@@ -305,11 +309,11 @@ def main():
epilog=f"""
v2 双固件模式(默认, 规格: UPGRADE_PLAN_v2.md):
python %(prog)s app_a.bin # 识别 A 包 → *_UPDATE.bin (+FULL)
python %(prog)s app_a.bin app_b.bin -b bl.bin # 全产物: UPDATE/B/FULL/md5
python %(prog)s app_a.bin app_b.bin -b bl.bin # 全产物: UPDATE/FULL/FACTORY/md5
python %(prog)s app_a.bin --no-full # 仅升级包
python %(prog)s app_b.bin -b bl.bin # 仅工厂镜像 → *_FACTORY.bin
python %(prog)s --a a.bin --b b.bin # 显式指定槽位(与向量表冲突报错)
python %(prog)s a.bin --profile f8_single_slot # 换布局(无保底槽)
python %(prog)s a.bin --profile my_layout.json # 自定义 profile JSON
python %(prog)s b.bin # 仅 B 底包 → *_B.bin
python %(prog)s a.bin --profile my_layout.json # 自定义布局 profile JSON
legacy 模式(旧单槽方案, -f/-m 触发):
python %(prog)s -f app.bin # 纯 0xFF 补齐升级包(无 trailer)
@@ -328,7 +332,7 @@ legacy 模式(旧单槽方案, -f/-m 触发):
help="legacy: 仅补齐 APP 到整页边界 (纯 0xFF, 无 trailer)")
parser.add_argument("--legacy", action="store_true",
help="显式声明 legacy 模式(需配合 -f/-m)")
parser.add_argument("--profile", default="ceramixnano_mb_v51",
parser.add_argument("--profile", default=DEFAULT_PROFILE,
help="v2 布局 profile: 内置名(%s)或 JSON 文件路径"
% "/".join(fw_pack.BUILTIN_PROFILES))
parser.add_argument("--a", metavar="BIN", default=None,
@@ -340,7 +344,9 @@ legacy 模式(旧单槽方案, -f/-m 触发):
parser.add_argument("-o", "--output", default=None,
help="输出路径: v2=输出目录(自动命名); legacy=输出文件")
parser.add_argument("--no-full", action="store_true",
help="v2: 只出 UPDATE/B 包, 不拼 FULL")
help="v2: 不拼 FULL 整片镜像")
parser.add_argument("--no-factory", action="store_true",
help="v2: 不出 FACTORY 工厂镜像")
parser.add_argument("-s", "--flash-size", default=DEFAULT_CHIP,
choices=list(CHIP_CONFIG.keys()),
help="legacy 芯片型号: F4(16K) F6(32K) F8(64K)")
@@ -353,10 +359,10 @@ legacy 模式(旧单槽方案, -f/-m 触发):
legacy = args.fill or args.merge
if args.legacy and not legacy:
parser.error("--legacy 需配合 -f/--fill 或 -m/--merge 使用")
if legacy and (args.profile != "ceramixnano_mb_v51" or args.a or args.b
or args.no_full or args.app_addr):
parser.error("--profile/--a/--b/--no-full/-a 是 v2/legacy 专属参数, "
"不能与 -f/-m 同用")
if legacy and (args.profile != DEFAULT_PROFILE or args.a or args.b
or args.no_full or args.no_factory or args.app_addr):
parser.error("--profile/--a/--b/--no-full/--no-factory/-a 是 v2/legacy "
"专属参数, 不能与 -f/-m 同用")
if legacy and len(args.bins) != 1:
parser.error("legacy 模式需要一个 APP 位置参数, 例: python %(prog)s -f app.bin"
% {'prog': parser.prog})