#!/usr/bin/env python3 """Firmware serial output must reach the host. App/main.c sends UART_Version over USART1 right after UART_Init(), and _putchar routes every printf_ there too. The machine has no USART1 model -- it is one of the logging catch-all stubs -- so without help those bytes vanish and the firmware appears to print nothing at all. Boots a real emulator on a private socket and checks the bytes come out of QEMU's stderr as SERIAL lines. Run: python3 tools/test_serial_capture.py """ import os import subprocess import sys import time HERE = os.path.dirname(os.path.abspath(__file__)) SIM = os.path.dirname(HERE) sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) import uvk5_testenv QEMU = uvk5_testenv.qemu() ELF = uvk5_testenv.firmware() FLASH = os.path.join(SIM, "assets", "flash.img") LOG = "/tmp/uvk5-serial-test.log" QMP = "/tmp/uvk5-serial-test.sock" def main(): missing = uvk5_testenv.missing([ (QEMU, "QEMU binary", "set QEMU=/path/to/qemu-system-arm, or put it on PATH"), (ELF, "firmware", "run tools/fetch_firmware.py, or set ELF=..."), (FLASH, "flash image", "run tools/make_flash.py"), ]) if missing: print("SKIP: %s" % missing) return 0 if os.path.exists(QMP): os.unlink(QMP) with open(LOG, "wb") as fh: proc = subprocess.Popen( [QEMU, "-M", f"uv-k5-v3,flash-image={FLASH}", "-nographic", "-monitor", "none", "-qmp", f"unix:{QMP},server=on,wait=off", "-kernel", ELF], stdout=subprocess.DEVNULL, stderr=fh) try: time.sleep(14) finally: proc.terminate() try: proc.wait(timeout=10) except subprocess.TimeoutExpired: proc.kill() if os.path.exists(QMP): os.unlink(QMP) # Explicit UTF-8: the firmware's own output is not always ASCII, and the locale # codec on Windows would mangle it (it cannot decode Chinese at all). text = open(LOG, encoding="utf-8", errors="replace").read() lines = [l for l in text.splitlines() if l.startswith("SERIAL")] print(f"captured {len(lines)} SERIAL line(s)") for line in lines[:10]: print(" ", line) if not lines: print("\nFAIL no SERIAL output; USART1 DR writes are still being dropped") print(" (App/main.c:98 sends UART_Version, so something should appear)") return 1 print("\nPASS firmware serial output reaches the host") return 0 if __name__ == "__main__": raise SystemExit(main())