#!/usr/bin/env python3 """The build-time OSCCAL trim, observed through the wire: a loader built with the OSCCAL axis holds the trim register at the built byte from its first prompt on - the write sits at the top of run(), ahead of the WDRF bail, so every path out of reset runs on the corrected clock. simavr's clock does not follow OSCCAL, which is what makes the value assertable at all: the register is plain state there, and the peek must return exactly what the build declared rather than whatever the oscillator needed. Usage: pbosccal.py [link] """ import os import sys def fail(message): print(f"FAIL: {message}") sys.exit(1) def main(): args = sys.argv[1:] link = args.pop() if len(args) == 12 else None (device_bin, elf, mcu, hz, base_hex, page, baud, addr, value, tool, workdir) = args addr, value, baud = int(addr, 0), int(value, 0), int(baud) sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) import pbsim os.makedirs(workdir, exist_ok=True) dump = os.path.join(workdir, "flash_dump.bin") device = pbsim.Device(device_bin, elf, mcu, hz, base_hex, page, baud, dump, link=link) try: out = pbsim.run_tool(tool, device.pty, baud, "--peek", f"{addr:#x}:1") want = f"{addr:#06x} {value:02x}" if want not in out: fail(f"OSCCAL at {addr:#x} did not read back {value:#04x}:\n{out}") finally: device.stop() print("OK") if __name__ == "__main__": main()