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>
This commit is contained in:
parent
f33df7197e
commit
a9803f4711
4 changed files with 28 additions and 23 deletions
|
|
@ -36,10 +36,7 @@ Use the :ref:`machine.Pin <machine.Pin>` class::
|
||||||
|
|
||||||
from machine import Pin
|
from machine import Pin
|
||||||
|
|
||||||
gpio1 = "gpio@400ff040" # GPIO1 device name
|
pin = Pin(("gpiob", 21), Pin.IN) # create input pin on GPIO port B
|
||||||
gpio2 = "gpio@400ff080" # GPIO2 device name
|
|
||||||
|
|
||||||
pin = Pin((gpio1, 21), Pin.IN) # create input pin on GPIO1
|
|
||||||
print(pin) # print pin port and number
|
print(pin) # print pin port and number
|
||||||
|
|
||||||
pin.init(Pin.OUT, Pin.PULL_UP, value=1) # reinitialize pin
|
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.on() # set pin to high
|
||||||
pin.off() # set pin to low
|
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 = 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
|
switch.irq(lambda t: print("SW2 changed")) # enable an interrupt when switch state is changed
|
||||||
|
|
||||||
Hardware I2C bus
|
Hardware I2C bus
|
||||||
----------------
|
----------------
|
||||||
|
|
@ -66,7 +63,7 @@ Hardware I2C is accessed via the :ref:`machine.I2C <machine.I2C>` class::
|
||||||
|
|
||||||
from machine import I2C
|
from machine import I2C
|
||||||
|
|
||||||
i2c = I2C("i2c@40066000") # construct an i2c bus
|
i2c = I2C("i2c0") # construct an i2c bus
|
||||||
print(i2c) # print device name
|
print(i2c) # print device name
|
||||||
|
|
||||||
i2c.scan() # scan the device for available I2C slaves
|
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
|
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
|
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
|
# 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
|
print(spi) # print device name and bus configuration
|
||||||
|
|
||||||
spi.read(4) # read 4 bytes on MISO
|
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
|
import zsensor
|
||||||
from zsensor import Sensor
|
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
|
accel.measure() # obtain a measurement reading from the accelerometer
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ To blink an LED:
|
||||||
import time
|
import time
|
||||||
from machine import Pin
|
from machine import Pin
|
||||||
|
|
||||||
LED = Pin(("gpio@400ff040", 21), Pin.OUT)
|
LED = Pin(("gpiob", 21), Pin.OUT)
|
||||||
while True:
|
while True:
|
||||||
LED.value(1)
|
LED.value(1)
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
|
|
@ -115,18 +115,18 @@ To blink an LED:
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
|
|
||||||
The above code uses an LED location for a FRDM-K64F board (port B, pin 21;
|
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*
|
following Zephyr conventions port are identified by their devicetree node
|
||||||
starts from 0). You will need to adjust it for another board (using board's
|
label. You will need to adjust it for another board (using board's reference
|
||||||
reference materials). To execute the above sample, copy it to clipboard, in
|
materials). To execute the above sample, copy it to clipboard, in MicroPython
|
||||||
MicroPython REPL enter "paste mode" using Ctrl+E, paste clipboard, press
|
REPL enter "paste mode" using Ctrl+E, paste clipboard, press Ctrl+D to finish
|
||||||
Ctrl+D to finish paste mode and start execution.
|
paste mode and start execution.
|
||||||
|
|
||||||
To respond to Pin change IRQs, on a FRDM-K64F board run:
|
To respond to Pin change IRQs, on a FRDM-K64F board run:
|
||||||
|
|
||||||
from machine import Pin
|
from machine import Pin
|
||||||
|
|
||||||
SW2 = Pin(("gpio@400ff080", 6), Pin.IN)
|
SW2 = Pin(("gpioc", 6), Pin.IN)
|
||||||
SW3 = Pin(("gpio@400ff000", 4), Pin.IN)
|
SW3 = Pin(("gpioa", 4), Pin.IN)
|
||||||
|
|
||||||
SW2.irq(lambda t: print("SW2 changed"))
|
SW2.irq(lambda t: print("SW2 changed"))
|
||||||
SW3.irq(lambda t: print("SW3 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
|
from machine import I2C
|
||||||
|
|
||||||
i2c = I2C("i2c@40066000")
|
i2c = I2C("i2c0")
|
||||||
i2c.scan()
|
i2c.scan()
|
||||||
|
|
||||||
Example of using SPI to write a buffer to the MOSI pin:
|
Example of using SPI to write a buffer to the MOSI pin:
|
||||||
|
|
||||||
from machine import SPI
|
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.init(baudrate=500000, polarity=1, phase=1, bits=8, firstbit=SPI.MSB)
|
||||||
spi.write(b'abcd')
|
spi.write(b'abcd')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@ CONFIG_FPU=y
|
||||||
CONFIG_MAIN_STACK_SIZE=4736
|
CONFIG_MAIN_STACK_SIZE=4736
|
||||||
CONFIG_POLL=y
|
CONFIG_POLL=y
|
||||||
|
|
||||||
|
CONFIG_DEVICE_DT_METADATA=y
|
||||||
|
|
||||||
# Enable sensor subsystem (doesn't add code if not used).
|
# Enable sensor subsystem (doesn't add code if not used).
|
||||||
# Specific sensors should be enabled per-board.
|
# Specific sensors should be enabled per-board.
|
||||||
CONFIG_SENSOR=y
|
CONFIG_SENSOR=y
|
||||||
|
|
|
||||||
|
|
@ -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 char *dev_name = mp_obj_str_get_str(name);
|
||||||
const struct device *dev = device_get_binding(dev_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 (dev == NULL) {
|
||||||
#if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE
|
#if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE
|
||||||
mp_raise_ValueError(MP_ERROR_TEXT("device not found"));
|
mp_raise_ValueError(MP_ERROR_TEXT("device not found"));
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue