From bf3b73e368a3ab63aea5c361fd5da908bc5a1e99 Mon Sep 17 00:00:00 2001 From: Maureen Helm Date: Sat, 25 Feb 2023 14:03:22 -0600 Subject: [PATCH] zephyr: Construct Pin object with a port instance number. Adds support for constructing a Pin object with a port instance number, where the available instances are defined by devicetree chosen nodes. Existing support for constructing a Pin object with a device name string remains, but device names will become less user-friendly when upgrading to Zephyr v3.2.0 due to deprecation of the devicetree label property. Signed-off-by: Maureen Helm --- docs/zephyr/quickref.rst | 10 +++++----- ports/zephyr/README.md | 6 +++--- ports/zephyr/boards/frdm_k64f.overlay | 15 +++++++++++++++ ports/zephyr/machine_pin.c | 20 +++++++++++++++++--- ports/zephyr/modmachine.h | 7 +++++++ 5 files changed, 47 insertions(+), 11 deletions(-) create mode 100644 ports/zephyr/boards/frdm_k64f.overlay diff --git a/docs/zephyr/quickref.rst b/docs/zephyr/quickref.rst index 329a9c41c0cc8..3d75faf1949a3 100644 --- a/docs/zephyr/quickref.rst +++ b/docs/zephyr/quickref.rst @@ -36,7 +36,7 @@ Use the :ref:`machine.Pin ` class:: from machine import Pin - pin = Pin(("GPIO_1", 21), Pin.IN) # create input pin on GPIO1 + pin = Pin((1, 21), Pin.IN) # create input pin on GPIO1 print(pin) # print pin port and number pin.init(Pin.OUT, Pin.PULL_UP, value=1) # reinitialize pin @@ -47,13 +47,13 @@ Use the :ref:`machine.Pin ` class:: pin.on() # set pin to high pin.off() # set pin to low - pin = Pin(("GPIO_1", 21), Pin.IN) # create input pin on GPIO1 + pin = Pin((1, 21), Pin.IN) # create input pin on GPIO1 - pin = Pin(("GPIO_1", 21), Pin.OUT, value=1) # set pin high on creation + pin = Pin((1, 21), Pin.OUT, value=1) # set pin high on creation - pin = Pin(("GPIO_1", 21), Pin.IN, Pin.PULL_UP) # enable internal pull-up resistor + pin = Pin((1, 21), Pin.IN, Pin.PULL_UP) # enable internal pull-up resistor - switch = Pin(("GPIO_2", 6), Pin.IN) # create input pin for a switch + switch = Pin((2, 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 diff --git a/ports/zephyr/README.md b/ports/zephyr/README.md index f9bd45344b322..9625162d97a9b 100644 --- a/ports/zephyr/README.md +++ b/ports/zephyr/README.md @@ -102,7 +102,7 @@ To blink an LED: import time from machine import Pin - LED = Pin(("GPIO_1", 21), Pin.OUT) + LED = Pin((1, 21), Pin.OUT) while True: LED.value(1) time.sleep(0.5) @@ -120,8 +120,8 @@ To respond to Pin change IRQs, on a FRDM-K64F board run: from machine import Pin - SW2 = Pin(("GPIO_2", 6), Pin.IN) - SW3 = Pin(("GPIO_0", 4), Pin.IN) + SW2 = Pin((2, 6), Pin.IN) + SW3 = Pin((0, 4), Pin.IN) SW2.irq(lambda t: print("SW2 changed")) SW3.irq(lambda t: print("SW3 changed")) diff --git a/ports/zephyr/boards/frdm_k64f.overlay b/ports/zephyr/boards/frdm_k64f.overlay new file mode 100644 index 0000000000000..7585e7d6cf8fc --- /dev/null +++ b/ports/zephyr/boards/frdm_k64f.overlay @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + chosen { + micropython,machine-pin0 = &gpioa; + micropython,machine-pin1 = &gpiob; + micropython,machine-pin2 = &gpioc; + micropython,machine-pin3 = &gpiod; + micropython,machine-pin4 = &gpioe; + }; +}; diff --git a/ports/zephyr/machine_pin.c b/ports/zephyr/machine_pin.c index be0698651bbf6..364992833a0ee 100644 --- a/ports/zephyr/machine_pin.c +++ b/ports/zephyr/machine_pin.c @@ -49,6 +49,10 @@ typedef struct _machine_pin_irq_obj_t { STATIC const mp_irq_methods_t machine_pin_irq_methods; const mp_obj_base_t machine_pin_obj_template = {&machine_pin_type}; +#define PIN_DEVICE(i, _) MICROPYTHON_CHOSEN_DEVICE(machine_pin, i, _) + +STATIC const struct device *const machine_pin_devices[] = {LISTIFY(8, PIN_DEVICE, ())}; + void machine_pin_deinit(void) { for (machine_pin_irq_obj_t *irq = MP_STATE_PORT(machine_pin_irq_list); irq != NULL; irq = irq->next) { machine_pin_obj_t *pin = MP_OBJ_TO_PTR(irq->base.parent); @@ -130,13 +134,23 @@ mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, } mp_obj_t *items; mp_obj_get_array_fixed_n(args[0], 2, &items); - const char *drv_name = mp_obj_str_get_str(items[0]); - int wanted_pin = mp_obj_get_int(items[1]); - const struct device *wanted_port = device_get_binding(drv_name); + + const struct device *wanted_port = NULL; + if (mp_obj_is_int(items[0])) { + int drv_instance = mp_obj_get_int(items[0]); + if (drv_instance < ARRAY_SIZE(machine_pin_devices)) { + wanted_port = machine_pin_devices[drv_instance]; + } + } else { + const char *drv_name = mp_obj_str_get_str(items[0]); + wanted_port = device_get_binding(drv_name); + } if (!wanted_port) { mp_raise_ValueError(MP_ERROR_TEXT("invalid port")); } + int wanted_pin = mp_obj_get_int(items[1]); + machine_pin_obj_t *pin = m_new_obj(machine_pin_obj_t); pin->base = machine_pin_obj_template; pin->port = wanted_port; diff --git a/ports/zephyr/modmachine.h b/ports/zephyr/modmachine.h index a605ada0de76c..517d8ea82a31f 100644 --- a/ports/zephyr/modmachine.h +++ b/ports/zephyr/modmachine.h @@ -3,6 +3,13 @@ #include "py/obj.h" +#define MICROPYTHON_CHOSEN(prop, i) \ + DT_CHOSEN(DT_CAT3(micropython_, prop, i)) + +#define MICROPYTHON_CHOSEN_DEVICE(prop, i, _) \ + IF_ENABLED(DT_NODE_EXISTS(MICROPYTHON_CHOSEN(prop, i)), \ + (DEVICE_DT_GET(MICROPYTHON_CHOSEN(prop, i)),)) + extern const mp_obj_type_t machine_pin_type; extern const mp_obj_type_t machine_i2c_type; extern const mp_obj_type_t machine_spi_type;