Skip to content

Commit a9803f4

Browse files
committed
zephyr: Allow using devicetree node labels to construct machine objects.
Zephyr v3.7.0 added a new feature to allow getting devices by their devicetree node labels. Use this feature in the MicroPython Zephyr port to simplify constructing machine module objects, including Pin, SPI, I2C, and UART. It's still possible to use the more verbose device names (e.g., gpio@400ff040, i2c@40066000, spi@4002c000), but now we can also use their devicetree node labels (e.g., gpiob, i2c0, spi0). Node labels aren't standardized across all SoC families because they generally try to follow their respective SoC hardware user manual naming convention, however many boards define common labels for devices routed to Arduino headers (e.g., arduino_i2c, arduino_serial, and arduino_spi). That means I2C("arduino_i2c") will work on quite a few boards (>100 in the main Zephyr tree). Signed-off-by: Maureen Helm <[email protected]>
1 parent f33df71 commit a9803f4

File tree

4 files changed

+28
-23
lines changed

4 files changed

+28
-23
lines changed

docs/zephyr/quickref.rst

+10-13
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,7 @@ Use the :ref:`machine.Pin <machine.Pin>` class::
3636

3737
from machine import Pin
3838

39-
gpio1 = "gpio@400ff040" # GPIO1 device name
40-
gpio2 = "gpio@400ff080" # GPIO2 device name
41-
42-
pin = Pin((gpio1, 21), Pin.IN) # create input pin on GPIO1
39+
pin = Pin(("gpiob", 21), Pin.IN) # create input pin on GPIO port B
4340
print(pin) # print pin port and number
4441

4542
pin.init(Pin.OUT, Pin.PULL_UP, value=1) # reinitialize pin
@@ -50,14 +47,14 @@ Use the :ref:`machine.Pin <machine.Pin>` class::
5047
pin.on() # set pin to high
5148
pin.off() # set pin to low
5249

53-
pin = Pin((gpio1, 21), Pin.IN) # create input pin on GPIO1
50+
pin = Pin(("gpiob", 21), Pin.IN) # create input pin on GPIO port B
5451

55-
pin = Pin((gpio1, 21), Pin.OUT, value=1) # set pin high on creation
52+
pin = Pin(("gpiob", 21), Pin.OUT, value=1) # set pin high on creation
5653

57-
pin = Pin((gpio1, 21), Pin.IN, Pin.PULL_UP) # enable internal pull-up resistor
54+
pin = Pin(("gpiob", 21), Pin.IN, Pin.PULL_UP) # enable internal pull-up resistor
5855

59-
switch = Pin((gpio2, 6), Pin.IN) # create input pin for a switch
60-
switch.irq(lambda t: print("SW2 changed")) # enable an interrupt when switch state is changed
56+
switch = Pin(("gpioc", 6), Pin.IN) # create input pin for a switch
57+
switch.irq(lambda t: print("SW2 changed")) # enable an interrupt when switch state is changed
6158

6259
Hardware I2C bus
6360
----------------
@@ -66,7 +63,7 @@ Hardware I2C is accessed via the :ref:`machine.I2C <machine.I2C>` class::
6663

6764
from machine import I2C
6865

69-
i2c = I2C("i2c@40066000") # construct an i2c bus
66+
i2c = I2C("i2c0") # construct an i2c bus
7067
print(i2c) # print device name
7168

7269
i2c.scan() # scan the device for available I2C slaves
@@ -87,11 +84,11 @@ Hardware SPI is accessed via the :ref:`machine.SPI <machine.SPI>` class::
8784

8885
from machine import SPI
8986

90-
spi = SPI("spi@4002c000") # construct a spi bus with default configuration
87+
spi = SPI("spi0") # construct a spi bus with default configuration
9188
spi.init(baudrate=100000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB) # set configuration
9289

9390
# equivalently, construct spi bus and set configuration at the same time
94-
spi = SPI("spi@4002c000", baudrate=100000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB)
91+
spi = SPI("spi0", baudrate=100000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB)
9592
print(spi) # print device name and bus configuration
9693

9794
spi.read(4) # read 4 bytes on MISO
@@ -149,7 +146,7 @@ Use the :ref:`zsensor.Sensor <zsensor.Sensor>` class to access sensor data::
149146
import zsensor
150147
from zsensor import Sensor
151148

152-
accel = Sensor("fxos8700@1d") # create sensor object for the accelerometer
149+
accel = Sensor("fxos8700") # create sensor object for the accelerometer
153150

154151
accel.measure() # obtain a measurement reading from the accelerometer
155152

ports/zephyr/README.md

+10-10
Original file line numberDiff line numberDiff line change
@@ -107,26 +107,26 @@ To blink an LED:
107107
import time
108108
from machine import Pin
109109

110-
LED = Pin(("gpio@400ff040", 21), Pin.OUT)
110+
LED = Pin(("gpiob", 21), Pin.OUT)
111111
while True:
112112
LED.value(1)
113113
time.sleep(0.5)
114114
LED.value(0)
115115
time.sleep(0.5)
116116

117117
The above code uses an LED location for a FRDM-K64F board (port B, pin 21;
118-
following Zephyr conventions port are identified by "GPIO_x", where *x*
119-
starts from 0). You will need to adjust it for another board (using board's
120-
reference materials). To execute the above sample, copy it to clipboard, in
121-
MicroPython REPL enter "paste mode" using Ctrl+E, paste clipboard, press
122-
Ctrl+D to finish paste mode and start execution.
118+
following Zephyr conventions port are identified by their devicetree node
119+
label. You will need to adjust it for another board (using board's reference
120+
materials). To execute the above sample, copy it to clipboard, in MicroPython
121+
REPL enter "paste mode" using Ctrl+E, paste clipboard, press Ctrl+D to finish
122+
paste mode and start execution.
123123

124124
To respond to Pin change IRQs, on a FRDM-K64F board run:
125125

126126
from machine import Pin
127127

128-
SW2 = Pin(("gpio@400ff080", 6), Pin.IN)
129-
SW3 = Pin(("gpio@400ff000", 4), Pin.IN)
128+
SW2 = Pin(("gpioc", 6), Pin.IN)
129+
SW3 = Pin(("gpioa", 4), Pin.IN)
130130

131131
SW2.irq(lambda t: print("SW2 changed"))
132132
SW3.irq(lambda t: print("SW3 changed"))
@@ -138,14 +138,14 @@ Example of using I2C to scan for I2C slaves:
138138

139139
from machine import I2C
140140

141-
i2c = I2C("i2c@40066000")
141+
i2c = I2C("i2c0")
142142
i2c.scan()
143143

144144
Example of using SPI to write a buffer to the MOSI pin:
145145

146146
from machine import SPI
147147

148-
spi = SPI("spi@4002c000")
148+
spi = SPI("spi0")
149149
spi.init(baudrate=500000, polarity=1, phase=1, bits=8, firstbit=SPI.MSB)
150150
spi.write(b'abcd')
151151

ports/zephyr/prj.conf

+2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ CONFIG_FPU=y
1616
CONFIG_MAIN_STACK_SIZE=4736
1717
CONFIG_POLL=y
1818

19+
CONFIG_DEVICE_DT_METADATA=y
20+
1921
# Enable sensor subsystem (doesn't add code if not used).
2022
# Specific sensors should be enabled per-board.
2123
CONFIG_SENSOR=y

ports/zephyr/zephyr_device.c

+6
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ const struct device *zephyr_device_find(mp_obj_t name) {
3131
const char *dev_name = mp_obj_str_get_str(name);
3232
const struct device *dev = device_get_binding(dev_name);
3333

34+
#ifdef CONFIG_DEVICE_DT_METADATA
35+
if (dev == NULL) {
36+
dev = device_get_by_dt_nodelabel(dev_name);
37+
}
38+
#endif
39+
3440
if (dev == NULL) {
3541
#if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE
3642
mp_raise_ValueError(MP_ERROR_TEXT("device not found"));

0 commit comments

Comments
 (0)