pureboot_device and the tsb device, C until now, rewritten in C++23 with every modeled behavior intact — the PGERS Z-mask and m48-discard ioctl wraps, the GPIO bridge's timing and pacing, the tiny NVM's write-once buffer, pin ownership, and the PB_PTY/TSB_PTY lines the harnesses parse. The one linkage fact worth a comment: simavr's parts headers (uart_pty.h) carry no C++ guards where its core headers do, so those includes sit in an extern "C" block. Warning-clean at -Wall -Wextra on the build line; the full protocol suites on all four sim-driven chips prove the conversion. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
74 lines
2.8 KiB
Python
74 lines
2.8 KiB
Python
#!/usr/bin/env python3
|
|
"""Hand-over with a USART left enabled on the loader's own pins.
|
|
|
|
A software or autobaud link deployed on a USART's TxD is mute if an
|
|
application hands over with that USART still enabled: TXEN keeps the USART
|
|
owning the pin, so the bit-banged transmitter's port writes go nowhere and the
|
|
loader receives and obeys while answering nothing. The link's init releases it.
|
|
|
|
The state is reached the way silicon reaches it — an application that sets up
|
|
its USART and jumps in with no reset between, so nothing clears UCSRnB for it.
|
|
The pin ownership itself is modelled by the device runner: simavr wires a
|
|
USART through IRQs alone and never takes the pin from the port, so without
|
|
that the mute could not happen here at all (test/pureboot_device.cpp).
|
|
|
|
Usage: pbmute.py <device_bin> <pureboot_elf> <mcu> <hz> <base_hex> <page>
|
|
<baud> <app_bin> <tool_py> <workdir> <link>
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
|
|
|
|
def fail(message):
|
|
print(f"FAIL: {message}")
|
|
sys.exit(1)
|
|
|
|
|
|
def main():
|
|
device_bin, elf, mcu, hz, base_hex, page, baud, app_bin, tool, workdir, link = sys.argv[1:]
|
|
page, baud = int(page), int(baud)
|
|
sys.path.insert(0, os.path.dirname(os.path.abspath(tool)))
|
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|
import pbsim
|
|
import pureboot as pb
|
|
|
|
if "@" not in link:
|
|
fail(f"the link {link} names no owning USART — nothing would be under test")
|
|
|
|
os.makedirs(workdir, exist_ok=True)
|
|
dump = os.path.join(workdir, "dump.bin")
|
|
|
|
device = pbsim.Device(device_bin, elf, mcu, hz, base_hex, page, baud, dump, link=link)
|
|
try:
|
|
port = pb.Port(device.pty, baud)
|
|
loader = pb.Loader(port)
|
|
loader.connect(25)
|
|
resident = loader.info.version
|
|
|
|
# Install the fixture and let it take over. It brings up the USART
|
|
# that owns these pins and jumps straight back in.
|
|
pb.op_flash(loader, app_bin, erase=False, verify=True)
|
|
loader.run_application()
|
|
|
|
# The loader is running again with that USART enabled behind it. Only
|
|
# the release makes it audible; without it the connect times out.
|
|
loader = pb.Loader(port)
|
|
try:
|
|
loader.connect(25)
|
|
except pb.Error as error:
|
|
fail(f"the loader never answered after the hand-over — the USART still owns its TX pin ({error})")
|
|
if loader.info.version != resident:
|
|
fail(f"identity changed across the hand-over: {resident} then {loader.info.version}")
|
|
|
|
# Answering is not enough: it has to still be a working loader.
|
|
pb.verify_pages(loader, pb.plan_flash(open(app_bin, "rb").read(), loader.info))
|
|
port.close()
|
|
finally:
|
|
device.stop()
|
|
print("pbmute: a loader on a USART's own pins answers after a hand-over that left it enabled")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|