- src/: прошивка встроенного отладчика BL616 — составное USB-устройство 1209:C0CA: DirtyJTAG v3 (WinUSB через MS OS 2.0) + CDC-ACM UART к FPGA B3/C3; UART до 20 Мбод на DMA, JTAG до 30 МГц через аппаратный SPI; - bin/: загрузчик Sipeed (0x0) и штатная прошивка 2025030317 для отката; - gui/: TangProgrammer.exe (C# WinForms, .NET Framework 4) — загрузка FPGA в SRAM и во флеш-память, копия и стирание флеш-памяти FPGA, прошивка моста; светлая и тёмная тема; - scripts/: setup, build, flash, build_gui, make_portable, а также make_release и publish_release для релизов Gitea; - fpga_test/, tests/: тестовые проекты Gowin (loopback, stream) и тесты UART на Python; - tools/openFPGALoader/: openFPGALoader 1.1.1 для Windows x64.
60 lines
1.9 KiB
Python
60 lines
1.9 KiB
Python
#!/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()
|