1dbd1b5151
Keep the current GPS software and Genesys2/VCU118 flows while integrating Ti375C529 Efinity, flash, programming, and debug support. Add board-specific SPI NOR profiles and persistent GPS flash layouts across all three boards.
127 lines
4.3 KiB
Python
127 lines
4.3 KiB
Python
#!/usr/bin/env python3
|
|
"""Build Efinity raw-HEX images for Ti375C529 persistent Rocket boot."""
|
|
|
|
import argparse
|
|
import hashlib
|
|
import json
|
|
import re
|
|
from pathlib import Path
|
|
|
|
|
|
HEX_BYTE = re.compile(r"[0-9a-fA-F]{2}")
|
|
|
|
|
|
def parse_int(value):
|
|
return int(value, 0)
|
|
|
|
|
|
def read_raw_hex(path):
|
|
data = bytearray()
|
|
with path.open() as source:
|
|
for line_number, line in enumerate(source, 1):
|
|
value = line.strip()
|
|
if not HEX_BYTE.fullmatch(value):
|
|
raise SystemExit(
|
|
f"{path}:{line_number}: expected one hexadecimal byte per line"
|
|
)
|
|
data.append(int(value, 16))
|
|
return bytes(data)
|
|
|
|
|
|
def write_raw_hex(path, chunks):
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
with path.open("w") as output:
|
|
for chunk in chunks:
|
|
for value in chunk:
|
|
output.write(f"{value:02X}\n")
|
|
|
|
|
|
def sha256(data):
|
|
return hashlib.sha256(data).hexdigest()
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(
|
|
description="Combine an Efinity configuration HEX and Rocket app image"
|
|
)
|
|
parser.add_argument("--config-hex", type=Path, required=True)
|
|
parser.add_argument("--app-bin", type=Path, required=True)
|
|
parser.add_argument("--app-offset", type=parse_int, required=True)
|
|
parser.add_argument("--flash-size", type=parse_int, default=0x04000000)
|
|
parser.add_argument("--nav-context-offset", type=parse_int, required=True)
|
|
parser.add_argument("--ephemeris-offset", type=parse_int, required=True)
|
|
parser.add_argument("--combined-hex", type=Path, required=True)
|
|
parser.add_argument("--app-hex", type=Path, required=True)
|
|
parser.add_argument("--manifest", type=Path, required=True)
|
|
args = parser.parse_args()
|
|
|
|
config = read_raw_hex(args.config_hex)
|
|
app = args.app_bin.read_bytes()
|
|
app_end = args.app_offset + len(app)
|
|
|
|
if args.app_offset & 0xFFFF:
|
|
raise SystemExit("application offset must be aligned to a 64-KiB sector")
|
|
if len(config) > args.app_offset:
|
|
raise SystemExit(
|
|
f"configuration image (0x{len(config):x} bytes) overlaps application "
|
|
f"at 0x{args.app_offset:x}"
|
|
)
|
|
if app_end > args.flash_size:
|
|
raise SystemExit(
|
|
f"application ends at 0x{app_end:x}, beyond flash size 0x{args.flash_size:x}"
|
|
)
|
|
reserved_size = 2 * 0x10000
|
|
if args.nav_context_offset + reserved_size > args.ephemeris_offset:
|
|
raise SystemExit("navigation context overlaps ephemeris flash region")
|
|
if args.ephemeris_offset + reserved_size > args.flash_size:
|
|
raise SystemExit("ephemeris flash region exceeds device capacity")
|
|
if app_end > args.nav_context_offset:
|
|
raise SystemExit(
|
|
f"application ends at 0x{app_end:x}, overlapping persistent data at "
|
|
f"0x{args.nav_context_offset:x}"
|
|
)
|
|
|
|
padding_size = args.app_offset - len(config)
|
|
write_raw_hex(args.app_hex, (app,))
|
|
write_raw_hex(args.combined_hex, (config, bytes([0xFF]) * padding_size, app))
|
|
|
|
manifest = {
|
|
"format": "Efinity raw HEX (one byte per line)",
|
|
"flash": "Ti375C529 lower SPI NOR (U47)",
|
|
"flash_size": f"0x{args.flash_size:08x}",
|
|
"configuration": {
|
|
"source": str(args.config_hex),
|
|
"offset": "0x00000000",
|
|
"size": len(config),
|
|
"sha256": sha256(config),
|
|
},
|
|
"application": {
|
|
"source": str(args.app_bin),
|
|
"offset": f"0x{args.app_offset:08x}",
|
|
"size": len(app),
|
|
"sha256": sha256(app),
|
|
},
|
|
"navigation_context": {
|
|
"offset": f"0x{args.nav_context_offset:08x}",
|
|
"size": reserved_size,
|
|
},
|
|
"ephemeris_cache": {
|
|
"offset": f"0x{args.ephemeris_offset:08x}",
|
|
"size": reserved_size,
|
|
},
|
|
"combined": {
|
|
"image": str(args.combined_hex),
|
|
"programmed_length": app_end,
|
|
},
|
|
}
|
|
args.manifest.parent.mkdir(parents=True, exist_ok=True)
|
|
args.manifest.write_text(json.dumps(manifest, indent=2) + "\n")
|
|
|
|
print(f"configuration: 0x00000000..0x{len(config) - 1:08x}")
|
|
print(f"application: 0x{args.app_offset:08x}..0x{app_end - 1:08x}")
|
|
print(f"combined HEX: {args.combined_hex}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|