mothercup/tools/merge_image.py
2026-09-02 07:53:48 +08:00

96 lines
3.1 KiB
Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
merge_image.py - Merge the CAIIC bootloader and application binaries into a
single flash package for N32WB031KEQ6-2 (512KB).
Inputs (produced by the Keil after-build fromelf step):
Boot/MDK-ARM/bin/caiic_boot.bin -> 0x01000000
mcm-ddc-04/MDK-ARM/bin/embeddedSrc.bin -> 0x01008000 (APP1 bank)
Outputs (written to tools/out/):
caiic_full.hex Intel HEX, sparse (gaps omitted) - for pyocd/NSpyocd/J-Flash
caiic_full.bin raw binary from 0x01000000, gaps padded with 0xFF
Usage: python tools/merge_image.py
Run from anywhere; paths are resolved relative to this script.
"""
import os
import sys
FLASH_BASE = 0x01000000
# (input bin relative to repo root, load address)
IMAGES = [
(os.path.join("Boot", "MDK-ARM", "bin", "caiic_boot.bin"), 0x01000000),
(os.path.join("mcm-ddc-04", "MDK-ARM", "bin", "embeddedSrc.bin"), 0x01008000),
]
OUT_DIR = "out"
HEX_NAME = "caiic_full.hex"
BIN_NAME = "caiic_full.bin"
HEX_REC_LEN = 16
def hex_record(addr, rectype, data):
"""Build one Intel HEX record string."""
body = [len(data), (addr >> 8) & 0xFF, addr & 0xFF, rectype] + list(data)
cks = (-sum(body)) & 0xFF
return ":" + "".join("%02X" % b for b in body) + "%02X" % cks + "\n"
def write_hex(path, segments):
"""Write segments [(base_addr, bytes)] as Intel HEX with ELA records."""
with open(path, "w") as f:
ela = None
for base, blob in segments:
for off in range(0, len(blob), HEX_REC_LEN):
addr = base + off
new_ela = addr >> 16
if new_ela != ela:
ela = new_ela
f.write(hex_record(0, 4, [(ela >> 8) & 0xFF, ela & 0xFF]))
f.write(hex_record(addr & 0xFFFF, 0, blob[off:off + HEX_REC_LEN]))
f.write(":00000001FF\n")
def main():
root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
segments = []
for rel, addr in IMAGES:
path = os.path.join(root, rel)
if not os.path.isfile(path):
print("ERROR: %s not found - build the Keil project first" % rel)
return 1
with open(path, "rb") as f:
blob = f.read()
segments.append((addr, blob))
print("%-46s -> 0x%08X (%d bytes)" % (rel, addr, len(blob)))
out_dir = os.path.join(root, "tools", OUT_DIR)
if not os.path.isdir(out_dir):
os.makedirs(out_dir)
hex_path = os.path.join(out_dir, HEX_NAME)
write_hex(hex_path, segments)
# merged bin: FLASH_BASE .. end of last segment, gaps padded with 0xFF
end = max(addr + len(blob) for addr, blob in segments)
merged = bytearray(b"\xFF" * (end - FLASH_BASE))
for addr, blob in segments:
merged[addr - FLASH_BASE: addr - FLASH_BASE + len(blob)] = blob
bin_path = os.path.join(out_dir, BIN_NAME)
with open(bin_path, "wb") as f:
f.write(bytes(merged))
print("")
print("package written:")
print(" %s" % hex_path)
print(" %s (base 0x%08X, %d bytes)" % (bin_path, FLASH_BASE, len(merged)))
return 0
if __name__ == "__main__":
sys.exit(main())