Commit 1e98c4cb authored by Angus Gratton's avatar Angus Gratton Committed by Damien George

tests/extmod: Add machine_spi_rate test.

Based on machine_i2s_rate, allows testing basic SPI functionality and
timings.

Implemented and confirmed working for rp2, esp32, and pyboard.

This work was funded through GitHub Sponsors.
Signed-off-by: default avatarAngus Gratton <angus@redyak.com.au>
parent a4b3825b
# Test machine.SPI data transfer rates
import sys
try:
import time
from machine import Pin, SPI
except ImportError:
print("SKIP")
raise SystemExit
MAX_DELTA_MS = 8
# Configure pins based on the port/board details.
# Values are tuples of (spi_id, sck, mosi, miso)
if "pyboard" in sys.platform:
spi_instances = (
(1, None, None, None), # "explicit choice of sck/mosi/miso is not implemented"
(2, None, None, None),
)
elif "rp2" in sys.platform:
spi_instances = ((0, Pin(18), Pin(19), Pin(16)),)
elif "esp32" in sys.platform:
spi_instances = [
(1, Pin(18), Pin(19), Pin(21)),
]
if "ESP32C3" not in str(sys.implementation):
spi_instances.append((2, Pin(18), Pin(19), Pin(21)))
else:
print("Please add support for this test on this platform.")
raise SystemExit
def get_real_baudrate(spi):
# Return the 'real' baudrate for a SPI object, from parsing 'print' output
# i.e.
# SPI(id=1, baudrate=500000, polarity=0, phase=0, bits=8, firstbit=0, sck=14, mosi=13, miso=12)
#
# Note the 'real' rate may be quite different to the requested rate, i.e.
# on ports where the SPI hardware only supports power of 2 clock dividers.
#
# Implementation is somewhat fiddly and inefficient to avoid dependency on
# 're' module,
s = str(spi)
s = s.split("baudrate=")[1].split(",")[0]
return int(s)
def test_instances():
print_results = True
for spi_id, sck, mosi, miso in spi_instances:
for baudrate in (
100_000,
250_000,
800_000,
1_000_000,
2_000_000,
4_000_000,
8_000_000,
):
test_spi(
spi_id,
sck,
mosi,
miso,
baudrate,
0,
0,
print_results,
)
for baudrate in (100_000, 4_000_000):
# Test the other polarity and phase settings
for polarity, phase in ((0, 1), (1, 0), (1, 1)):
test_spi(
spi_id,
sck,
mosi,
miso,
baudrate,
polarity,
phase,
print_results,
)
# Ensure the same test output regardless of how many SPI instances are tested
print_results = False
wr_short = b"abcdefghijklmnop" * 10
rd_short = bytearray(len(wr_short))
wr_long = wr_short * 20
rd_long = bytearray(len(wr_long))
def test_spi(spi_id, sck, mosi, miso, baudrate, polarity, phase, print_results):
if sck:
s = SPI(
spi_id,
sck=sck,
mosi=mosi,
miso=miso,
baudrate=baudrate,
polarity=polarity,
phase=phase,
)
else:
s = SPI(spi_id, baudrate=baudrate, polarity=polarity, phase=phase)
# to keep the test runtime down, use shorter buffer for lower baud rate
wr_buf = wr_long if baudrate > 500_000 else wr_short
rd_buf = rd_long if baudrate > 500_000 else rd_short
real_baudrate = get_real_baudrate(s)
assert real_baudrate
transfer_time_ms = len(wr_buf) * 8 * 1000 // real_baudrate
def test_write_readinto():
s.write_readinto(wr_buf, rd_buf)
def test_write():
s.write(wr_buf)
def test_readinto():
s.readinto(rd_buf)
for test_func, name in (
(test_write_readinto, "write_readinto"),
(test_write, "write"),
(test_readinto, "readinto"),
):
t0 = time.ticks_ms()
test_func()
transfer_time = time.ticks_diff(time.ticks_ms(), t0)
t_delta = abs(transfer_time - transfer_time_ms)
t_ok = t_delta < MAX_DELTA_MS
if print_results or not t_ok:
print(
None if print_results else spi_id,
baudrate,
polarity,
phase,
name,
t_ok or t_delta,
)
s.deinit()
test_instances()
None 100000 0 0 write_readinto True
None 100000 0 0 write True
None 100000 0 0 readinto True
None 250000 0 0 write_readinto True
None 250000 0 0 write True
None 250000 0 0 readinto True
None 800000 0 0 write_readinto True
None 800000 0 0 write True
None 800000 0 0 readinto True
None 1000000 0 0 write_readinto True
None 1000000 0 0 write True
None 1000000 0 0 readinto True
None 2000000 0 0 write_readinto True
None 2000000 0 0 write True
None 2000000 0 0 readinto True
None 4000000 0 0 write_readinto True
None 4000000 0 0 write True
None 4000000 0 0 readinto True
None 8000000 0 0 write_readinto True
None 8000000 0 0 write True
None 8000000 0 0 readinto True
None 100000 0 1 write_readinto True
None 100000 0 1 write True
None 100000 0 1 readinto True
None 100000 1 0 write_readinto True
None 100000 1 0 write True
None 100000 1 0 readinto True
None 100000 1 1 write_readinto True
None 100000 1 1 write True
None 100000 1 1 readinto True
None 4000000 0 1 write_readinto True
None 4000000 0 1 write True
None 4000000 0 1 readinto True
None 4000000 1 0 write_readinto True
None 4000000 1 0 write True
None 4000000 1 0 readinto True
None 4000000 1 1 write_readinto True
None 4000000 1 1 write True
None 4000000 1 1 readinto True
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment