#!/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())