summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaureen Helm <maureen.helm@analog.com>2024-08-05 12:58:36 -0500
committerMaureen Helm <maureen.helm@analog.com>2024-10-01 20:02:01 -0500
commita9803f47115ff2319232e89b6c4c5b380bad5c2b (patch)
tree309dbad27d086597c29faa7b7d24b72361f25cf9
parentf33df7197e30db1e0ede3632a0baebf8f711d7d2 (diff)
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>
-rw-r--r--docs/zephyr/quickref.rst23
-rw-r--r--ports/zephyr/README.md20
-rw-r--r--ports/zephyr/prj.conf2
-rw-r--r--ports/zephyr/zephyr_device.c6
4 files changed, 28 insertions, 23 deletions
diff --git a/docs/zephyr/quickref.rst b/docs/zephyr/quickref.rst
index 31a4ac46c..63d4bced0 100644
--- a/docs/zephyr/quickref.rst
+++ b/docs/zephyr/quickref.rst
@@ -36,10 +36,7 @@ Use the :ref:`machine.Pin <machine.Pin>` class::
from machine import Pin
- gpio1 = "gpio@400ff040" # GPIO1 device name
- gpio2 = "gpio@400ff080" # GPIO2 device name
-
- pin = Pin((gpio1, 21), Pin.IN) # create input pin on GPIO1
+ pin = Pin(("gpiob", 21), Pin.IN) # create input pin on GPIO port B
print(pin) # print pin port and number
pin.init(Pin.OUT, Pin.PULL_UP, value=1) # reinitialize pin
@@ -50,14 +47,14 @@ Use the :ref:`machine.Pin <machine.Pin>` class::
pin.on() # set pin to high
pin.off() # set pin to low
- pin = Pin((gpio1, 21), Pin.IN) # create input pin on GPIO1
+ pin = Pin(("gpiob", 21), Pin.IN) # create input pin on GPIO port B
- pin = Pin((gpio1, 21), Pin.OUT, value=1) # set pin high on creation
+ pin = Pin(("gpiob", 21), Pin.OUT, value=1) # set pin high on creation
- pin = Pin((gpio1, 21), Pin.IN, Pin.PULL_UP) # enable internal pull-up resistor
+ pin = Pin(("gpiob", 21), Pin.IN, Pin.PULL_UP) # enable internal pull-up resistor
- switch = Pin((gpio2, 6), Pin.IN) # create input pin for a switch
- switch.irq(lambda t: print("SW2 changed")) # enable an interrupt when switch state is changed
+ switch = Pin(("gpioc", 6), Pin.IN) # create input pin for a switch
+ switch.irq(lambda t: print("SW2 changed")) # enable an interrupt when switch state is changed
Hardware I2C bus
----------------
@@ -66,7 +63,7 @@ Hardware I2C is accessed via the :ref:`machine.I2C <machine.I2C>` class::
from machine import I2C
- i2c = I2C("i2c@40066000") # construct an i2c bus
+ i2c = I2C("i2c0") # construct an i2c bus
print(i2c) # print device name
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::
from machine import SPI
- spi = SPI("spi@4002c000") # construct a spi bus with default configuration
+ spi = SPI("spi0") # construct a spi bus with default configuration
spi.init(baudrate=100000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB) # set configuration
# equivalently, construct spi bus and set configuration at the same time
- spi = SPI("spi@4002c000", baudrate=100000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB)
+ spi = SPI("spi0", baudrate=100000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB)
print(spi) # print device name and bus configuration
spi.read(4) # read 4 bytes on MISO
@@ -149,7 +146,7 @@ Use the :ref:`zsensor.Sensor <zsensor.Sensor>` class to access sensor data::
import zsensor
from zsensor import Sensor
- accel = Sensor("fxos8700@1d") # create sensor object for the accelerometer
+ accel = Sensor("fxos8700") # create sensor object for the accelerometer
accel.measure() # obtain a measurement reading from the accelerometer
diff --git a/ports/zephyr/README.md b/ports/zephyr/README.md
index 39010b2ac..4590eb719 100644
--- a/ports/zephyr/README.md
+++ b/ports/zephyr/README.md
@@ -107,7 +107,7 @@ To blink an LED:
import time
from machine import Pin
- LED = Pin(("gpio@400ff040", 21), Pin.OUT)
+ LED = Pin(("gpiob", 21), Pin.OUT)
while True:
LED.value(1)
time.sleep(0.5)
@@ -115,18 +115,18 @@ To blink an LED:
time.sleep(0.5)
The above code uses an LED location for a FRDM-K64F board (port B, pin 21;
-following Zephyr conventions port are identified by "GPIO_x", where *x*
-starts from 0). You will need to adjust it for another board (using board's
-reference materials). To execute the above sample, copy it to clipboard, in
-MicroPython REPL enter "paste mode" using Ctrl+E, paste clipboard, press
-Ctrl+D to finish paste mode and start execution.
+following Zephyr conventions port are identified by their devicetree node
+label. You will need to adjust it for another board (using board's reference
+materials). To execute the above sample, copy it to clipboard, in MicroPython
+REPL enter "paste mode" using Ctrl+E, paste clipboard, press Ctrl+D to finish
+paste mode and start execution.
To respond to Pin change IRQs, on a FRDM-K64F board run:
from machine import Pin
- SW2 = Pin(("gpio@400ff080", 6), Pin.IN)
- SW3 = Pin(("gpio@400ff000", 4), Pin.IN)
+ SW2 = Pin(("gpioc", 6), Pin.IN)
+ SW3 = Pin(("gpioa", 4), Pin.IN)
SW2.irq(lambda t: print("SW2 changed"))
SW3.irq(lambda t: print("SW3 changed"))
@@ -138,14 +138,14 @@ Example of using I2C to scan for I2C slaves:
from machine import I2C
- i2c = I2C("i2c@40066000")
+ i2c = I2C("i2c0")
i2c.scan()
Example of using SPI to write a buffer to the MOSI pin:
from machine import SPI
- spi = SPI("spi@4002c000")
+ spi = SPI("spi0")
spi.init(baudrate=500000, polarity=1, phase=1, bits=8, firstbit=SPI.MSB)
spi.write(b'abcd')
diff --git a/ports/zephyr/prj.conf b/ports/zephyr/prj.conf
index d3983fcc2..eac04216c 100644
--- a/ports/zephyr/prj.conf
+++ b/ports/zephyr/prj.conf
@@ -16,6 +16,8 @@ CONFIG_FPU=y
CONFIG_MAIN_STACK_SIZE=4736
CONFIG_POLL=y
+CONFIG_DEVICE_DT_METADATA=y
+
# Enable sensor subsystem (doesn't add code if not used).
# Specific sensors should be enabled per-board.
CONFIG_SENSOR=y
diff --git a/ports/zephyr/zephyr_device.c b/ports/zephyr/zephyr_device.c
index 2ef331742..51784bc78 100644
--- a/ports/zephyr/zephyr_device.c
+++ b/ports/zephyr/zephyr_device.c
@@ -31,6 +31,12 @@ const struct device *zephyr_device_find(mp_obj_t name) {
const char *dev_name = mp_obj_str_get_str(name);
const struct device *dev = device_get_binding(dev_name);
+ #ifdef CONFIG_DEVICE_DT_METADATA
+ if (dev == NULL) {
+ dev = device_get_by_dt_nodelabel(dev_name);
+ }
+ #endif
+
if (dev == NULL) {
#if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE
mp_raise_ValueError(MP_ERROR_TEXT("device not found"));