--scan's walk was unwalkable on POSIX: probe rates have no termios B-constant, so the first off-nominal probe raised out of the loop. The port speaks termios2 BOTHER now (red-proven on a pty at 9984 Bd), the probe's open lives inside the walk's error handling, an fd no longer leaks on an unmakeable rate, and the swallowed unknown-signature reply is named at timeout instead of reported as silence. CMakePresets.json's generator emits the submodule toolchain path it had drifted from — a hand edit on a generated file, exactly the class rule 10 exists for — and presets.generated gates the pair from here on (the marker CMake rejects at the presets root stayed out; the check is the guard). The over-slot image guard the tsb runner gained reaches the pureboot runner too; the GPIO bridge's delivery comment states the hardware truth (RXC at the stop bit's sampling point); the hardware suite gains the scan check — the one place the rate physics is real; and the libavr pin advances over both audit rounds. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
72 lines
2.4 KiB
Python
72 lines
2.4 KiB
Python
#!/usr/bin/env python3
|
|
"""--scan's walk and report logic, no simulator: the probe order, the rate
|
|
arithmetic, and the advice's direction. The rate physics itself is not
|
|
sim-testable — a pty carries bytes at any termios rate — so what the wire
|
|
would arbitrate is pinned here as logic instead.
|
|
|
|
Usage: test_scan.py <tool_py>
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
|
|
|
|
def fail(message):
|
|
print(f"FAIL: {message}")
|
|
sys.exit(1)
|
|
|
|
|
|
def main():
|
|
sys.path.insert(0, os.path.dirname(os.path.abspath(sys.argv[1])))
|
|
import pureboot as pb
|
|
|
|
walk = pb.scan_ratios()
|
|
if walk != [0, -2, 2, -4, 4, -6, 6, -8, 8, -10, 10]:
|
|
fail(f"probe walk is not built-rate-first, nearest-out: {walk}")
|
|
|
|
if pb.scan_rate(9600, 4) != 9984 or pb.scan_rate(9600, -4) != 9216:
|
|
fail("probe rate arithmetic")
|
|
if pb.scan_rate(115200, 0) != 115200:
|
|
fail("the built rate must probe unchanged")
|
|
|
|
# A loader answering fast means a fast oscillator: the trim goes down.
|
|
report = "\n".join(pb.scan_report(9600, 4, 6))
|
|
for needle in ("9984", "+4 %", "--baud 9984", "4 steps lower", "pureboot 6"):
|
|
if needle not in report:
|
|
fail(f"+4 % report lacks {needle!r}:\n{report}")
|
|
report = "\n".join(pb.scan_report(9600, -6, 6))
|
|
if "6 steps higher" not in report:
|
|
fail(f"-6 % report advises the wrong direction:\n{report}")
|
|
|
|
report = "\n".join(pb.scan_report(9600, 0, 6))
|
|
if "none" not in report or "steps" in report:
|
|
fail(f"an on-rate answer must advise no trim:\n{report}")
|
|
|
|
report = "\n".join(pb.scan_report(9600, 4, 6, clock=9600000))
|
|
if "9984000" not in report:
|
|
fail(f"the absolute clock must scale with the found ratio:\n{report}")
|
|
|
|
# The walk's rates mostly have no termios B-constant, so the POSIX port
|
|
# must set them through termios2 — probed on a pty, which accepts the
|
|
# ioctl without caring about the speed. Without this every off-nominal
|
|
# probe would abort the walk on the platform --scan matters most on.
|
|
if os.name == "posix":
|
|
import pty
|
|
|
|
master, slave = pty.openpty()
|
|
try:
|
|
port = pb.Port(os.ttyname(slave), pb.scan_rate(9600, 4))
|
|
port.set_baud(pb.scan_rate(9600, -4))
|
|
port.close()
|
|
except pb.Error as error:
|
|
fail(f"PosixPort refused an off-nominal probe rate: {error}")
|
|
finally:
|
|
os.close(master)
|
|
os.close(slave)
|
|
|
|
print("OK")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|