1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
# 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 "alif" in sys.platform:
MAX_DELTA_MS = 20
spi_instances = ((0, None, None, None),)
elif "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:
impl = str(sys.implementation)
if "ESP32C3" in impl or "ESP32C6" in impl:
spi_instances = ((1, Pin(4), Pin(5), Pin(6)),)
else:
spi_instances = ((1, Pin(18), Pin(19), Pin(21)), (2, Pin(18), Pin(19), Pin(21)))
elif "esp8266" in sys.platform:
MAX_DELTA_MS = 50 # port requires much looser timing requirements
spi_instances = ((1, None, None, None),) # explicit pin choice not allowed
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()
|