#!/usr/bin/env python3 """ FPGA -> PC stream test with fpga_test/stream loaded into the FPGA: the FPGA sends a byte counter at exactly 10 Mbaud (1 MB/s) from its own 50 MHz clock. Checks absolute baud accuracy and that no byte is lost or corrupted. --switches N first reopens the port N times at other baud rates while the stream keeps coming (the BL616 receiver used to lock up on such changes). python tests/uart_stream_test.py --port COM12 --seconds 20 --switches 10 """ import argparse import random import sys import time import serial def main(): ap = argparse.ArgumentParser() ap.add_argument('--port', required=True) ap.add_argument('--baud', type=int, default=10_000_000) ap.add_argument('--seconds', type=float, default=10) ap.add_argument('--switches', type=int, default=0) args = ap.parse_args() for i in range(args.switches): other = random.choice([9600, 115200, 921600, 3_000_000, 12_000_000]) with serial.Serial(args.port, other, timeout=0.05) as s: time.sleep(random.uniform(0.02, 0.2)) s.read(65536) with serial.Serial(args.port, args.baud, timeout=0.1) as s: s.set_buffer_size(rx_size=1 << 20) time.sleep(0.3) s.reset_input_buffer() expect = None total = errors = 0 t0 = time.time() while time.time() - t0 < args.seconds: buf = s.read(65536) for b in buf: if expect is not None and b != expect: errors += 1 expect = (b + 1) & 0xFF total += len(buf) dt = time.time() - t0 rate = total / dt print(f'received {total} bytes in {dt:.1f} s = {rate / 1e6:.3f} MB/s ' f'({rate * 10 / 1e6:.2f} Mbaud of 8N1 payload), sequence errors: {errors}') ok = errors == 0 and rate > 0.97e6 * args.baud / 10_000_000 print('PASS' if ok else 'FAIL') sys.exit(0 if ok else 1) if __name__ == '__main__': main()