Files
gd32e230f8_firmware_merge_tool/merge_bin.py
T

119 lines
4.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""
合成 GD32E230 初始烧录固件:bootloader + app → 完整 64KB Flash 镜像。
布局:
0x08000000 ┌──────────────┐
│ Bootloader │
APP_ADDR ├──────────────┤
│ Application │
│ ... │
FLAG_ADDR │ 0xEEEE标志 │
0x08010000 └──────────────┘
空白区域填充 0xFF(Flash 擦除后的默认值)。
用法:
python merge_bin.py bootloader.bin app.bin -o merged.bin
python merge_bin.py bootloader.bin app.bin --app-addr 0x08002000 --flag-addr 0x0800FFFC -o merged.bin
"""
import argparse
import struct
import sys
import os
FLASH_BASE = 0x08000000
FLASH_SIZE = 64 * 1024 # 64KB
DEFAULT_BOOTLOADER = "gd32e230f8_bootloader_hulk.bin"
def merge(bootloader_path, app_path, output_path, app_addr, flag_addr):
app_offset = app_addr - FLASH_BASE
flag_offset = flag_addr - FLASH_BASE
# 校验地址合法性
if app_offset < 0 or app_offset >= FLASH_SIZE:
print(f"错误:APP 地址 0x{app_addr:08X} 超出 Flash 范围", file=sys.stderr)
return False
if flag_offset < 0 or flag_offset + 4 > FLASH_SIZE:
print(f"错误:标志地址 0x{flag_addr:08X} 超出 Flash 范围", file=sys.stderr)
return False
# 读取文件
with open(bootloader_path, "rb") as f:
bootloader = f.read()
with open(app_path, "rb") as f:
app = f.read()
# 校验 bootloader 不超过 APP 起始地址
if len(bootloader) > app_offset:
print(f"错误:Bootloader ({len(bootloader)} 字节) 超过 APP 偏移 ({app_offset} 字节)", file=sys.stderr)
return False
# 校验 APP 不超过 flag 地址
app_end = app_offset + len(app)
if app_end > flag_offset:
print(f"错误:APP 结束地址 0x{FLASH_BASE + app_end:08X} 超过标志地址 0x{flag_addr:08X}", file=sys.stderr)
return False
# 创建 64KB 的 Flash 镜像,填充 0xFF
image = bytearray(b'\xFF' * FLASH_SIZE)
# 写入 bootloader(从 offset 0 开始)
image[0:len(bootloader)] = bootloader
# 写入 APP(从 app_offset 开始)
image[app_offset:app_offset + len(app)] = app
# 写入标志位 0xEEEEEEEElittle-endian uint32,填满 0x0800FFFC~0x0800FFFF
struct.pack_into("<I", image, flag_offset, 0xEEEEEEEE)
# 输出
with open(output_path, "wb") as f:
f.write(image)
print(f"合成完成: {output_path}")
print(f" Bootloader : {len(bootloader):>6} 字节 @ 0x{FLASH_BASE:08X}")
print(f" Application: {len(app):>6} 字节 @ 0x{app_addr:08X}")
print(f" Flag : 0xEEEE @ 0x{flag_addr:08X}")
print(f" 总大小 : {FLASH_SIZE:>6} 字节 ({FLASH_SIZE // 1024}KB)")
return True
def main():
parser = argparse.ArgumentParser(description="合成 GD32E230 初始烧录固件 (bootloader + app)")
parser.add_argument("app", help="Application bin 文件路径")
parser.add_argument(
"-b",
"--bootloader",
default=DEFAULT_BOOTLOADER,
help=f"Bootloader bin 文件路径 (默认: {DEFAULT_BOOTLOADER})",
)
parser.add_argument("-o", "--output", default=None, help="输出文件路径 (默认: APP文件名_BL.bin)")
parser.add_argument("--app-addr", default="0x08002000", help="APP 起始地址 (默认: 0x08002000)")
parser.add_argument("--flag-addr", default="0x0800FFFC", help="标志位地址 (默认: 0x0800FFFC)")
args = parser.parse_args()
if args.output is None:
base, ext = os.path.splitext(os.path.basename(args.app))
args.output = f"{base}_BL{ext}"
app_addr = int(args.app_addr, 0)
flag_addr = int(args.flag_addr, 0)
if not os.path.isfile(args.bootloader):
print(f"错误:找不到文件 {args.bootloader}", file=sys.stderr)
sys.exit(1)
if not os.path.isfile(args.app):
print(f"错误:找不到文件 {args.app}", file=sys.stderr)
sys.exit(1)
if not merge(args.bootloader, args.app, args.output, app_addr, flag_addr):
sys.exit(1)
if __name__ == "__main__":
main()