#!/usr/bin/env python3 """合并Bootloader和主程序的Intel HEX文件。""" from __future__ import annotations import argparse from pathlib import Path EOF_RECORD = ":00000001FF" def read_records(path: Path) -> list[str]: """读取HEX记录,并去掉输入文件末尾的EOF记录。""" records = [] for raw_line in path.read_text(encoding="ascii").splitlines(): line = raw_line.strip().upper() if not line: continue if not line.startswith(":"): raise ValueError(f"{path}包含非法HEX记录:{line}") if line != EOF_RECORD: records.append(line) return records def record_range(record: str) -> tuple[int, int] | None: """返回数据记录地址范围,用于检查两个镜像是否重叠。""" count = int(record[1:3], 16) record_type = int(record[7:9], 16) if record_type != 0x00 or count == 0: return None address = int(record[3:7], 16) return address, address + count def merge(output: Path, inputs: list[Path]) -> None: """合并绝对地址HEX文件,并检查数据区间重叠。""" occupied: list[tuple[int, int, Path]] = [] records: list[str] = [] for path in inputs: for record in read_records(path): current = record_range(record) if current is not None: start, end = current for old_start, old_end, old_path in occupied: if start < old_end and old_start < end: raise ValueError( f"HEX地址重叠:{path} 0x{start:04X}~0x{end - 1:04X}," f"与 {old_path} 冲突" ) occupied.append((start, end, path)) records.append(record) output.write_text("\n".join(records + [EOF_RECORD]) + "\n", encoding="ascii") def main() -> None: """解析参数并执行HEX合并。""" parser = argparse.ArgumentParser(description="合并STM8 Bootloader和主程序HEX") parser.add_argument("output", type=Path, help="输出HEX文件") parser.add_argument("inputs", nargs="+", type=Path, help="输入HEX文件") args = parser.parse_args() merge(args.output, args.inputs) if __name__ == "__main__": main()