Skip to content

Commit 277b615

Browse files
committed
tests/multi_extmod: Add I2CTarget multi tests.
These require two boards wired together, SCL-SCL and SDA-SDA. Signed-off-by: Damien George <[email protected]>
1 parent 6558d51 commit 277b615

File tree

4 files changed

+247
-0
lines changed

4 files changed

+247
-0
lines changed
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
# Test I2CTarget IRQs and clock stretching.
2+
#
3+
# Requires two instances with their SCL and SDA lines connected together.
4+
# Any combination of the below supported boards can be used.
5+
#
6+
# Notes:
7+
# - pull-up resistors may be needed
8+
# - alif use 1.8V signalling
9+
10+
import sys
11+
import time
12+
from machine import I2C, I2CTarget
13+
14+
if not hasattr(I2CTarget, "IRQ_ADDR_MATCH_READ"):
15+
print("SKIP")
16+
raise SystemExit
17+
18+
ADDR = 67
19+
clock_stretch_us = 200
20+
21+
# Configure pins based on the target.
22+
if sys.platform == "alif":
23+
i2c_args = (1,) # pins P3_7/P3_6
24+
i2c_kwargs = {}
25+
elif sys.platform == "mimxrt":
26+
i2c_args = (0,) # pins 19/18 on Teensy 4.x
27+
i2c_kwargs = {}
28+
clock_stretch_us = 50 # mimxrt cannot delay too long in the IRQ handler
29+
elif sys.platform == "rp2":
30+
i2c_args = (0,)
31+
i2c_kwargs = {"scl": 9, "sda": 8}
32+
elif sys.platform == "pyboard":
33+
i2c_args = ("Y",)
34+
i2c_kwargs = {}
35+
elif sys.platform == "samd":
36+
i2c_args = () # pins SCL/SDA
37+
i2c_kwargs = {}
38+
elif "zephyr-rpi_pico" in sys.implementation._machine:
39+
i2c_args = ("i2c1",) # on gpio7/gpio6
40+
i2c_kwargs = {}
41+
else:
42+
print("Please add support for this test on this platform.")
43+
raise SystemExit
44+
45+
46+
def simple_irq(i2c_target):
47+
flags = i2c_target.irq().flags()
48+
if flags & I2CTarget.IRQ_ADDR_MATCH_READ:
49+
print("IRQ_ADDR_MATCH_READ")
50+
if flags & I2CTarget.IRQ_ADDR_MATCH_WRITE:
51+
print("IRQ_ADDR_MATCH_WRITE")
52+
53+
# Force clock stretching.
54+
time.sleep_us(clock_stretch_us)
55+
56+
57+
class I2CTargetMemory:
58+
def __init__(self, i2c_target, mem):
59+
self.buf1 = bytearray(1)
60+
self.mem = mem
61+
self.memaddr = 0
62+
self.state = 0
63+
i2c_target.irq(
64+
self.irq,
65+
I2CTarget.IRQ_ADDR_MATCH_WRITE | I2CTarget.IRQ_READ_REQ | I2CTarget.IRQ_WRITE_REQ,
66+
hard=True,
67+
)
68+
69+
def irq(self, i2c_target):
70+
# Force clock stretching.
71+
time.sleep_us(clock_stretch_us)
72+
73+
flags = i2c_target.irq().flags()
74+
if flags & I2CTarget.IRQ_ADDR_MATCH_WRITE:
75+
self.state = 0
76+
if flags & I2CTarget.IRQ_READ_REQ:
77+
self.buf1[0] = self.mem[self.memaddr]
78+
self.memaddr += 1
79+
i2c_target.write(self.buf1)
80+
if flags & I2CTarget.IRQ_WRITE_REQ:
81+
i2c_target.readinto(self.buf1)
82+
if self.state == 0:
83+
self.state = 1
84+
self.memaddr = self.buf1[0]
85+
else:
86+
self.mem[self.memaddr] = self.buf1[0]
87+
self.memaddr += 1
88+
self.memaddr %= len(self.mem)
89+
90+
# Force clock stretching.
91+
time.sleep_us(clock_stretch_us)
92+
93+
94+
# I2C controller
95+
def instance0():
96+
i2c = I2C(*i2c_args, **i2c_kwargs)
97+
multitest.next()
98+
for iteration in range(2):
99+
print("controller iteration", iteration)
100+
multitest.wait("target stage 1")
101+
i2c.writeto_mem(ADDR, 2, "0123")
102+
multitest.broadcast("controller stage 2")
103+
multitest.wait("target stage 3")
104+
print(i2c.readfrom_mem(ADDR, 2, 4))
105+
multitest.broadcast("controller stage 4")
106+
print("done")
107+
108+
109+
# I2C target
110+
def instance1():
111+
multitest.next()
112+
113+
for iteration in range(2):
114+
print("target iteration", iteration)
115+
buf = bytearray(b"--------")
116+
if iteration == 0:
117+
# Use built-in memory capability of I2CTarget.
118+
i2c_target = I2CTarget(*i2c_args, **i2c_kwargs, addr=ADDR, mem=buf)
119+
i2c_target.irq(
120+
simple_irq,
121+
I2CTarget.IRQ_ADDR_MATCH_READ | I2CTarget.IRQ_ADDR_MATCH_WRITE,
122+
hard=True,
123+
)
124+
else:
125+
# Implement a memory device by hand.
126+
i2c_target = I2CTarget(*i2c_args, **i2c_kwargs, addr=ADDR)
127+
I2CTargetMemory(i2c_target, buf)
128+
129+
multitest.broadcast("target stage 1")
130+
multitest.wait("controller stage 2")
131+
print(buf)
132+
multitest.broadcast("target stage 3")
133+
multitest.wait("controller stage 4")
134+
135+
i2c_target.deinit()
136+
137+
print("done")
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
--- instance0 ---
2+
controller iteration 0
3+
b'0123'
4+
controller iteration 1
5+
b'0123'
6+
done
7+
--- instance1 ---
8+
target iteration 0
9+
IRQ_ADDR_MATCH_WRITE
10+
bytearray(b'--0123--')
11+
IRQ_ADDR_MATCH_WRITE
12+
IRQ_ADDR_MATCH_READ
13+
target iteration 1
14+
bytearray(b'--0123--')
15+
done
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# Test basic use of I2CTarget and a memory buffer.
2+
#
3+
# Requires two instances with their SCL and SDA lines connected together.
4+
# Any combination of the below supported boards can be used.
5+
#
6+
# Notes:
7+
# - pull-up resistors may be needed
8+
# - alif use 1.8V signalling
9+
10+
import sys
11+
from machine import I2C, I2CTarget
12+
13+
ADDR = 67
14+
15+
# Configure pins based on the target.
16+
if sys.platform == "alif":
17+
i2c_args = (1,) # pins P3_7/P3_6
18+
i2c_kwargs = {}
19+
elif sys.platform == "esp32":
20+
i2c_args = (1,) # on pins 9/8
21+
i2c_kwargs = {}
22+
elif sys.platform == "mimxrt":
23+
i2c_args = (0,) # pins 19/18 on Teensy 4.x
24+
i2c_kwargs = {}
25+
elif sys.platform == "rp2":
26+
i2c_args = (0,)
27+
i2c_kwargs = {"scl": 9, "sda": 8}
28+
elif sys.platform == "pyboard":
29+
i2c_args = ("Y",)
30+
i2c_kwargs = {}
31+
elif sys.platform == "samd":
32+
i2c_args = () # pins SCL/SDA
33+
i2c_kwargs = {}
34+
elif "zephyr-rpi_pico" in sys.implementation._machine:
35+
i2c_args = ("i2c1",) # on gpio7/gpio6
36+
i2c_kwargs = {}
37+
else:
38+
print("Please add support for this test on this platform.")
39+
raise SystemExit
40+
41+
42+
def simple_irq(i2c_target):
43+
flags = i2c_target.irq().flags()
44+
if flags & I2CTarget.IRQ_END_READ:
45+
print("IRQ_END_READ", i2c_target.memaddr)
46+
if flags & I2CTarget.IRQ_END_WRITE:
47+
print("IRQ_END_WRITE", i2c_target.memaddr)
48+
49+
50+
# I2C controller
51+
def instance0():
52+
i2c = I2C(*i2c_args, **i2c_kwargs)
53+
multitest.next()
54+
for iteration in range(2):
55+
print("controller iteration", iteration)
56+
multitest.wait("target stage 1")
57+
i2c.writeto_mem(ADDR, 2 + iteration, "0123")
58+
multitest.broadcast("controller stage 2")
59+
multitest.wait("target stage 3")
60+
print(i2c.readfrom_mem(ADDR, 2 + iteration, 4))
61+
multitest.broadcast("controller stage 4")
62+
print("done")
63+
64+
65+
# I2C target
66+
def instance1():
67+
buf = bytearray(b"--------")
68+
i2c_target = I2CTarget(*i2c_args, **i2c_kwargs, addr=ADDR, mem=buf)
69+
i2c_target.irq(simple_irq)
70+
multitest.next()
71+
for iteration in range(2):
72+
print("target iteration", iteration)
73+
multitest.broadcast("target stage 1")
74+
multitest.wait("controller stage 2")
75+
print(buf)
76+
multitest.broadcast("target stage 3")
77+
multitest.wait("controller stage 4")
78+
i2c_target.deinit()
79+
print("done")
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
--- instance0 ---
2+
controller iteration 0
3+
b'0123'
4+
controller iteration 1
5+
b'0123'
6+
done
7+
--- instance1 ---
8+
target iteration 0
9+
IRQ_END_WRITE 2
10+
bytearray(b'--0123--')
11+
IRQ_END_READ 2
12+
target iteration 1
13+
IRQ_END_WRITE 3
14+
bytearray(b'--00123-')
15+
IRQ_END_READ 3
16+
done

0 commit comments

Comments
 (0)