Files
bootloader/test/pbmute.py
BlackMark 321ff8a4ee test: the device runners speak the C++ the rest of the repo does
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>
2026-07-28 13:59:03 +02:00

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()