8000 zephyr: Allow using devicetree node labels to construct machine objects. · micropython/micropython@7e8563a · GitHub
[go: up one dir, main page]

Skip to content

Commit 7e8563a

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 <maureen.helm@analog.com>
1 parent 6603eab commit 7e8563a

File tree

8 files changed

+70
-25
lines changed

8 files changed

+70
-25
lines changed

docs/zephyr/quickref.rst

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@ 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
39+
gpiob = "gpiob" # GPIO port B devicetree node label
40+
gpioc = "gpioc" # GPIO port C devicetree node label
4141

42-
pin = Pin((gpio1, 21), Pin.IN) # create input pin on GPIO1
42+
pin = Pin((gpiob, 21), Pin.IN) # create input pin on GPIO port B
4343
print(pin) # print pin port and number
4444

4545
pin.init(Pin.OUT, Pin.PULL_UP, value=1) # reinitialize pin
@@ -50,13 +50,13 @@ Use the :ref:`machine.Pin <machine.Pin>` class::
5050
pin.on() # set pin to high
5151
pin.off() # set pin to low
5252

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

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

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

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

6262
Hardware I2C bus
@@ -66,7 +66,7 @@ Hardware I2C is accessed via the :ref:`machine.I2C <machine.I2C>` class::
6666

6767
from machine import I2C
6868

69-
i2c = I2C("i2c@40066000") # construct an i2c bus
69+
i2c = I2C("i2c0") # construct an i2c bus
7070
print(i2c) # print device name
7171

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

8888
from machine import SPI
8989

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

9393
# 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)
94+
spi = SPI("spi0", baudrate=100000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB)
9595
print(spi) # print device name and bus configuration
9696

9797
spi.read(4) # read 4 bytes on MISO
@@ -149,7 +149,7 @@ Use the :ref:`zsensor.Sensor <zsensor.Sensor>` class to access sensor data::
149149
import zsensor
150150
from zsensor import Sensor
151151

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

154154
accel.measure() # obtain a measurement reading from the accelerometer
155155

ports/zephyr/README.md

Lines changed: 10 additions & 10 deletions
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/machine_i2c.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@ mp_obj_t machine_hard_i2c_make_new(const mp_obj_type_t *type, size_t n_args, siz
6767
const char *dev_name = mp_obj_str_get_str(args[ARG_id].u_obj);
6868
const struct device *dev = device_get_binding(dev_name);
6969

70+
#ifdef CONFIG_DEVICE_DT_METADATA
71+
if (dev == NULL) {
72+
dev = device_get_by_dt_nodelabel(dev_name);
73+
}
74+
#endif
75+
7076
if (dev == NULL) {
7177
mp_raise_ValueError(MP_ERROR_TEXT("device not found"));
7278
}

ports/zephyr/machine_pin.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,15 @@ mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw,
133133
mp_obj_get_array_fixed_n(args[0], 2, &items);
134134
const char *drv_name = mp_obj_str_get_str(items[0]);
135135
int wanted_pin = mp_obj_get_int(items[1]);
136+
136137
const struct device *wanted_port = device_get_binding(drv_name);
138+
139+
#ifdef CONFIG_DEVICE_DT_METADATA
140+
if (wanted_port == NULL) {
141+
wanted_port = device_get_by_dt_nodelabel(drv_name);
142+
}
143+
#endif
144+
137145
if (!wanted_port) {
138146
mp_raise_ValueError(MP_ERROR_TEXT("invalid port"));
139147
}

ports/zephyr/machine_spi.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,12 @@ mp_obj_t machine_hard_spi_make_new(const mp_obj_type_t *type, size_t n_args, siz
8484
const char *dev_name = mp_obj_str_get_str(args[ARG_id].u_obj);
8585
const struct device *dev = device_get_binding(dev_name);
8686

87+
#ifdef CONFIG_DEVICE_DT_METADATA
88+
if (dev == NULL) {
89+
dev = device_get_by_dt_nodelabel(dev_name);
90+
}
91+
#endif
92+
8793
if (dev == NULL) {
8894
mp_raise_ValueError(MP_ERROR_TEXT("device not found"));
8995
}

ports/zephyr/machine_uart.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,15 +75,26 @@ static mp_obj_t mp_machine_uart_make_new(const mp_obj_type_t *type, size_t n_arg
7575
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
7676

7777
machine_uart_obj_t *self = mp_obj_malloc(machine_uart_obj_t, &machine_uart_type);
78-
self->dev = device_get_binding(mp_obj_str_get_str(args[0]));
79-
if (!self->dev) {
78+
79+
const char *dev_name = mp_obj_str_get_str(args[0]);
80+
const struct device *dev = device_get_binding(dev_name);
81+
82+
#ifdef CONFIG_DEVICE_DT_METADATA
83+
if (dev == NULL) {
84+
dev = device_get_by_dt_nodelabel(dev_name);
85+
}
86+
#endif
87+
88+
if (dev == NULL) {
8089
mp_raise_ValueError(MP_ERROR_TEXT("Bad device name"));
8190
}
8291

8392
mp_map_t kw_args;
8493
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
8594
mp_machine_uart_init_helper(self, n_args - 1, args + 1, &kw_args);
8695

96+
self->dev = dev;
97+
8798
return MP_OBJ_FROM_PTR(self);
8899
}
89100

ports/zephyr/modzsensor.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,22 @@ typedef struct _mp_obj_sensor_t {
4141
static mp_obj_t sensor_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
4242
mp_arg_check_num(n_args, n_kw, 1, 1, false);
4343
mp_obj_sensor_t *o = mp_obj_malloc(mp_obj_sensor_t, type);
44-
o->dev = device_get_binding(mp_obj_str_get_str(args[0]));
45-
if (o->dev == NULL) {
44+
45+
const char *dev_name = mp_obj_str_get_str(args[0]);
46+
const struct device *dev = device_get_binding(dev_name);
47+
48+
#ifdef CONFIG_DEVICE_DT_METADATA
49+
if (dev == NULL) {
50+
dev = device_get_by_dt_nodelabel(dev_name);
51+
}
52+
#endif
53+
54+
if (dev == NULL) {
4655
mp_raise_ValueError(MP_ERROR_TEXT("dev not found"));
4756
}
57+
58+
o->dev = dev;
59+
4860
return MP_OBJ_FROM_PTR(o);
4961
}
5062

ports/zephyr/prj.conf

Lines changed: 2 additions & 0 deletions
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

0 commit comments

Comments
 (0)
0