#!/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.c). Usage: pbmute.py """ 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()