From a969339dfa98f57165f56d0adcd2aed41ad295d9 Mon Sep 17 00:00:00 2001 From: TOKITA Hiroshi Date: Wed, 20 Aug 2025 20:48:15 +0900 Subject: [PATCH 1/3] zephyrCommon: Changing pin numbering rules Zephyr's ba48d83b changes make it easy to configure pin numbering at compile, so we'll change the pin numbers to be based on the GPIO pin numbers. This is same as the traditional Arduino, using the GPIO numbers as pin numbers. Pin names written on the board, such as D1 and D2, are aliases for these pin numbers. When using multiple GPIO ports, pin numbers are numbered consecutively from the beginning. For example, if you have two 16-port GPIOs, 16 refers to the first pin (idx=0) of the second port. Signed-off-by: TOKITA Hiroshi --- cores/arduino/Arduino.h | 101 +++------ cores/arduino/zephyrCommon.cpp | 207 +++++++++--------- documentation/variants.md | 14 ++ .../arduino_mkrzero_samd21g18a.overlay | 1 + .../arduino_nano_33_ble_nrf52840.overlay | 1 + ...arduino_nano_33_ble_nrf52840_sense.overlay | 1 + .../arduino_nano_33_iot_samd21g18a.overlay | 1 + .../beagleconnect_freedom_cc1352p7.overlay | 2 + .../cc3220sf_launchxl_cc3220sf.overlay | 2 + variants/cc3220sf_launchxl_cc3220sf/variant.h | 8 +- .../nrf52840dk_nrf52840.overlay | 2 + .../nrf9160dk_nrf9160.overlay | 2 + .../rpi_pico_rp2040/rpi_pico_rp2040.overlay | 1 + 13 files changed, 165 insertions(+), 178 deletions(-) diff --git a/cores/arduino/Arduino.h b/cores/arduino/Arduino.h index e9399e72e..78126673f 100644 --- a/cores/arduino/Arduino.h +++ b/cores/arduino/Arduino.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2022 Dhruva Gole + * Copyright (c) 2025 TOKITA Hiroshi * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,87 +15,31 @@ #include #include -#define DIGITAL_PIN_EXISTS(n, p, i, dev, num) \ - (((dev == DT_REG_ADDR(DT_PHANDLE_BY_IDX(n, p, i))) && \ - (num == DT_PHA_BY_IDX(n, p, i, pin))) \ - ? 1 \ - : 0) - -/* Check all pins are defined only once */ -#define DIGITAL_PIN_CHECK_UNIQUE(i, _) \ - ((DT_FOREACH_PROP_ELEM_SEP_VARGS( \ - DT_PATH(zephyr_user), digital_pin_gpios, DIGITAL_PIN_EXISTS, (+), \ - DT_REG_ADDR(DT_PHANDLE_BY_IDX(DT_PATH(zephyr_user), digital_pin_gpios, i)), \ - DT_PHA_BY_IDX(DT_PATH(zephyr_user), digital_pin_gpios, i, pin))) == 1) - -#if !LISTIFY(DT_PROP_LEN(DT_PATH(zephyr_user), digital_pin_gpios), DIGITAL_PIN_CHECK_UNIQUE, (&&)) -#error "digital_pin_gpios has duplicate definition" -#endif - -#undef DIGITAL_PIN_CHECK_UNIQUE - -#ifndef LED_BUILTIN - -/* Return the index of it if matched, oterwise return 0 */ -#define LED_BUILTIN_INDEX_BY_REG_AND_PINNUM(n, p, i, dev, num) \ - (DIGITAL_PIN_EXISTS(n, p, i, dev, num) ? i : 0) - -/* Only matched pin returns non-zero value, so the sum is matched pin's index */ -#define DIGITAL_PIN_GPIOS_FIND_PIN(dev, pin) \ - DT_FOREACH_PROP_ELEM_SEP_VARGS(DT_PATH(zephyr_user), digital_pin_gpios, \ - LED_BUILTIN_INDEX_BY_REG_AND_PINNUM, (+), dev, pin) - -#if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), builtin_led_gpios) && \ - (DT_PROP_LEN(DT_PATH(zephyr_user), builtin_led_gpios) > 0) - -#if !(DT_FOREACH_PROP_ELEM_SEP_VARGS( \ - DT_PATH(zephyr_user), digital_pin_gpios, DIGITAL_PIN_EXISTS, (+), \ - DT_REG_ADDR(DT_PHANDLE_BY_IDX(DT_PATH(zephyr_user), builtin_led_gpios, 0)), \ - DT_PHA_BY_IDX(DT_PATH(zephyr_user), builtin_led_gpios, 0, pin)) > 0) -#warning "pin not found in digital_pin_gpios" -#else -#define LED_BUILTIN \ - DIGITAL_PIN_GPIOS_FIND_PIN( \ - DT_REG_ADDR(DT_PHANDLE_BY_IDX(DT_PATH(zephyr_user), builtin_led_gpios, 0)), \ - DT_PHA_BY_IDX(DT_PATH(zephyr_user), builtin_led_gpios, 0, pin)) -#endif - -/* If digital-pin-gpios is not defined, tries to use the led0 alias */ -#elif DT_NODE_EXISTS(DT_ALIAS(led0)) - -#if !(DT_FOREACH_PROP_ELEM_SEP_VARGS(DT_PATH(zephyr_user), digital_pin_gpios, DIGITAL_PIN_EXISTS, \ - (+), DT_REG_ADDR(DT_PHANDLE_BY_IDX(DT_ALIAS(led0), gpios, 0)), \ - DT_PHA_BY_IDX(DT_ALIAS(led0), gpios, 0, pin)) > 0) -#warning "pin not found in digital_pin_gpios" -#else -#define LED_BUILTIN \ - DIGITAL_PIN_GPIOS_FIND_PIN(DT_REG_ADDR(DT_PHANDLE_BY_IDX(DT_ALIAS(led0), gpios, 0)), \ - DT_PHA_BY_IDX(DT_ALIAS(led0), gpios, 0, pin)) -#endif - -#endif // builtin_led_gpios - -#endif // LED_BUILTIN - -#define DN_ENUMS(n, p, i) D##i = i +#define ZARD_ADD_NGPIOS(i, n, p) DT_PROP(DT_PROP_BY_IDX(n, p, i), ngpios) + +#define ZARD_ACCUM_NGPIOS(n, p, i, nd) \ + COND_CODE_1(DT_SAME_NODE(DT_PROP_BY_IDX(n, p, i), nd), \ + (LISTIFY(i, ZARD_ADD_NGPIOS, (), n, p)), ()) +#define ZARD_GLOBAL_GPIO_NUM(n, p, i) \ + DT_FOREACH_PROP_ELEM_VARGS(DT_PATH(zephyr_user), gpio_ports, ZARD_ACCUM_NGPIOS, \ + DT_PHANDLE_BY_IDX(n, p, i)) \ + DT_PHA_BY_IDX(n, p, i, pin) /* * expand as - * enum digitalPins { D0, D1, ... LED... NUM_OF_DIGITAL_PINS }; + * enum digitalPins { D0, D1, ... }; */ +#define ZARD_DN_ENUMS(n, p, i) D##i = ZARD_GLOBAL_GPIO_NUM(n, p, i) enum digitalPins { - DT_FOREACH_PROP_ELEM_SEP(DT_PATH(zephyr_user), digital_pin_gpios, DN_ENUMS, (, )), - NUM_OF_DIGITAL_PINS + DT_FOREACH_PROP_ELEM_SEP(DT_PATH(zephyr_user), digital_pin_gpios, ZARD_DN_ENUMS, (, )), + NUM_OF_DIGITAL_PINS }; #ifdef CONFIG_ADC - -#define AN_ENUMS(n, p, i) A ## i = DIGITAL_PIN_GPIOS_FIND_PIN( \ - DT_REG_ADDR(DT_PHANDLE_BY_IDX(DT_PATH(zephyr_user), p, i)), \ - DT_PHA_BY_IDX(DT_PATH(zephyr_user), p, i, pin)), -enum analogPins { DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), - adc_pin_gpios, AN_ENUMS) }; - +#define ZARD_AN_ENUMS(n, p, i) A##i = ZARD_GLOBAL_GPIO_NUM(n, p, i) +enum analogPins { + DT_FOREACH_PROP_ELEM_SEP(DT_PATH(zephyr_user), adc_pin_gpios, ZARD_AN_ENUMS, (, )), + NUM_OF_ANALOG_PINS +}; #endif void interrupts(void); @@ -103,6 +48,16 @@ void noInterrupts(void); int digitalPinToInterrupt(pin_size_t pin); #include + +#ifndef LED_BUILTIN +#if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), builtin_led_gpios) \ + && (DT_PROP_LEN(DT_PATH(zephyr_user), builtin_led_gpios) > 0) +#define LED_BUILTIN ZARD_GLOBAL_GPIO_NUM(DT_PATH(zephyr_user), builtin_led_gpios, 0) +#elif DT_NODE_EXISTS(DT_ALIAS(led0)) +#define LED_BUILTIN ZARD_GLOBAL_GPIO_NUM(DT_ALIAS(led0), gpios, 0) +#endif +#endif // LED_BUILTIN + #ifdef __cplusplus #include #include diff --git a/cores/arduino/zephyrCommon.cpp b/cores/arduino/zephyrCommon.cpp index 92d99ff02..ac62d9970 100644 --- a/cores/arduino/zephyrCommon.cpp +++ b/cores/arduino/zephyrCommon.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2022 Dhruva Gole + * Copyright (c) 2025 TOKITA Hiroshi * * SPDX-License-Identifier: Apache-2.0 */ @@ -7,24 +8,64 @@ #include #include "zephyrInternal.h" -static const struct gpio_dt_spec arduino_pins[] = {DT_FOREACH_PROP_ELEM_SEP( - DT_PATH(zephyr_user), digital_pin_gpios, GPIO_DT_SPEC_GET_BY_IDX, (, ))}; - namespace { -/* - * Calculate GPIO ports/pins number statically from devicetree configuration - */ +#define DEVICE_GPIO(n, p, i) DEVICE_DT_GET(DT_PROP_BY_IDX(n, p, i)) +constexpr const struct device *gpios[] = { + DT_FOREACH_PROP_ELEM_SEP(DT_PATH(zephyr_user), gpio_ports, DEVICE_GPIO, (,)) +}; -template constexpr const N sum_of_list(const N sum, const Head &head) -{ - return sum + head; +#define PROP_NGPIOS(n, p, i) DT_PROP(DT_PROP_BY_IDX(n, p, i), ngpios) +constexpr uint32_t pins[] = { + DT_FOREACH_PROP_ELEM_SEP(DT_PATH(zephyr_user), gpio_ports, PROP_NGPIOS, (,)) +}; + +constexpr inline const struct device *local_gpio_port_r(pin_size_t pin, + const struct device *const *ctrl, + const uint32_t accum, + const uint32_t *end, size_t n) { + return (n == 0) ? nullptr + : (pin < accum + end[0]) ? ctrl[0] + : local_gpio_port_r(pin, ctrl + 1, accum + end[0], end + 1, n - 1); } -template -constexpr const N sum_of_list(const N sum, const Head &head, const Tail &...tail) -{ - return sum_of_list(sum + head, tail...); +constexpr inline size_t port_index_r(const struct device *target, + const struct device *const *table, pin_size_t idx, size_t n) { + return (n == 0) ? size_t(-1) + : (target == table[0]) ? idx + : port_index_r(target, table + 1, idx + 1, n - 1); +} + +constexpr inline const struct device *local_gpio_port(pin_size_t gpin) { + return local_gpio_port_r(gpin, gpios, 0, pins, ARRAY_SIZE(gpios)); +} + +constexpr inline pin_size_t port_idx(pin_size_t gpin) { + return port_index_r(local_gpio_port(gpin), gpios, 0, ARRAY_SIZE(gpios)); +} + +constexpr inline pin_size_t end_accum_r(const uint32_t accum, const uint32_t *end, size_t n) { + return (n == 0) ? accum : end_accum_r(accum + end[0], end + 1, n - 1); +} + +constexpr inline pin_size_t end_accum(size_t n) { + return end_accum_r(0, pins, n); +} + +constexpr inline pin_size_t local_gpio_pin(pin_size_t gpin) { + return port_idx(gpin) == pin_size_t(-1) ? pin_size_t(-1) : gpin - end_accum(port_idx(gpin)); +} + +constexpr inline pin_size_t global_gpio_pin_(size_t port_idx, pin_size_t lpin) { + return port_idx == size_t(-1) ? size_t(-1) : end_accum(port_idx) + lpin; +} + +constexpr inline pin_size_t global_gpio_pin(const struct device *lport, pin_size_t lpin) { + return global_gpio_pin_(port_index_r(lport, gpios, 0, ARRAY_SIZE(gpios)), lpin); +} + +inline int global_gpio_pin_configure(pin_size_t pinNumber, int flags) { + return gpio_pin_configure(local_gpio_port(pinNumber), local_gpio_pin(pinNumber), flags); } template constexpr const N max_in_list(const N max, const Head &head) @@ -38,34 +79,8 @@ constexpr const N max_in_list(const N max, const Head &head, const Tail &...tail return max_in_list((max >= head) ? max : head, tail...); } -template -constexpr const size_t is_first_appearance(const size_t &idx, const size_t &at, const size_t &found, - const Query &query, const Head &head) -{ - return ((found == ((size_t)-1)) && (query == head) && (idx == at)) ? 1 : 0; -} - -template -constexpr const size_t is_first_appearance(const size_t &idx, const size_t &at, const size_t &found, - const Query &query, const Head &head, - const Tail &...tail) -{ - return ((found == ((size_t)-1)) && (query == head) && (idx == at)) - ? 1 - : is_first_appearance(idx + 1, at, (query == head ? idx : found), query, - tail...); -} - -#define GET_DEVICE_VARGS(n, p, i, _) DEVICE_DT_GET(DT_GPIO_CTLR_BY_IDX(n, p, i)) -#define FIRST_APPEARANCE(n, p, i) \ - is_first_appearance(0, i, ((size_t)-1), DEVICE_DT_GET(DT_GPIO_CTLR_BY_IDX(n, p, i)), \ - DT_FOREACH_PROP_ELEM_SEP_VARGS(n, p, GET_DEVICE_VARGS, (, ), 0)) -const int port_num = - sum_of_list(0, DT_FOREACH_PROP_ELEM_SEP(DT_PATH(zephyr_user), digital_pin_gpios, - FIRST_APPEARANCE, (, ))); - #define GPIO_NGPIOS(n, p, i) DT_PROP(DT_GPIO_CTLR_BY_IDX(n, p, i), ngpios) -const int max_ngpios = max_in_list( +constexpr int max_ngpios = max_in_list( 0, DT_FOREACH_PROP_ELEM_SEP(DT_PATH(zephyr_user), digital_pin_gpios, GPIO_NGPIOS, (, ))); /* @@ -82,7 +97,7 @@ struct gpio_port_callback { struct arduino_callback handlers[max_ngpios]; gpio_port_pins_t pins; const struct device *dev; -} port_callback[port_num] = {0}; +} port_callback[ARRAY_SIZE(gpios)]; struct gpio_port_callback *find_gpio_port_callback(const struct device *dev) { @@ -101,10 +116,10 @@ struct gpio_port_callback *find_gpio_port_callback(const struct device *dev) void setInterruptHandler(pin_size_t pinNumber, voidFuncPtr func) { - struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port); + struct gpio_port_callback *pcb = find_gpio_port_callback(local_gpio_port(pinNumber)); if (pcb) { - pcb->handlers[arduino_pins[pinNumber].pin].handler = func; + pcb->handlers[local_gpio_pin(pinNumber)].handler = func; } } @@ -121,18 +136,16 @@ void handleGpioCallback(const struct device *port, struct gpio_callback *cb, uin #ifdef CONFIG_PWM -#define PWM_DT_SPEC(n,p,i) PWM_DT_SPEC_GET_BY_IDX(n, i), -#define PWM_PINS(n, p, i) \ - DIGITAL_PIN_GPIOS_FIND_PIN( \ - DT_REG_ADDR(DT_PHANDLE_BY_IDX(DT_PATH(zephyr_user), p, i)), \ - DT_PHA_BY_IDX(DT_PATH(zephyr_user), p, i, pin)), +#define PWM_DT_SPEC(n, p, i) PWM_DT_SPEC_GET_BY_IDX(n, i) -const struct pwm_dt_spec arduino_pwm[] = - { DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), pwms, PWM_DT_SPEC) }; +const struct pwm_dt_spec arduino_pwm[] = { + DT_FOREACH_PROP_ELEM_SEP(DT_PATH(zephyr_user), pwms, PWM_DT_SPEC, (,)) +}; /* pwm-pins node provides a mapping digital pin numbers to pwm channels */ -const pin_size_t arduino_pwm_pins[] = - { DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), pwm_pin_gpios, PWM_PINS) }; +const pin_size_t arduino_pwm_pins[] = { + DT_FOREACH_PROP_ELEM_SEP(DT_PATH(zephyr_user), pwm_pin_gpios, ZARD_GLOBAL_GPIO_NUM, (,)) +}; size_t pwm_pin_index(pin_size_t pinNumber) { for(size_t i=0; ipin]; if (pt->count == 0) { k_timer_stop(timer); - gpio_pin_set_dt(spec, 0); + gpio_pin_set(local_gpio_port(pt->pin), local_gpio_pin(pt->pin), 0); } else { - gpio_pin_toggle_dt(spec); + gpio_pin_toggle(local_gpio_port(pt->pin), local_gpio_pin(pt->pin)); if (!pt->infinity) { pt->count--; } @@ -242,7 +249,6 @@ void tone_expiry_cb(struct k_timer *timer) { void tone(pin_size_t pinNumber, unsigned int frequency, unsigned long duration) { - const struct gpio_dt_spec *spec = &arduino_pins[pinNumber]; struct k_timer *timer; k_timeout_t timeout; @@ -256,7 +262,7 @@ void tone(pin_size_t pinNumber, unsigned int frequency, k_timer_stop(&arduino_pin_timers[pinNumber].timer); if (frequency == 0) { - gpio_pin_set_dt(spec, 0); + gpio_pin_set(local_gpio_port(pinNumber), local_gpio_pin(pinNumber), 0); return; } @@ -271,15 +277,13 @@ void tone(pin_size_t pinNumber, unsigned int frequency, arduino_pin_timers[pinNumber].pin = pinNumber; k_timer_init(timer, tone_expiry_cb, NULL); - gpio_pin_set_dt(spec, 0); + gpio_pin_set(local_gpio_port(pinNumber), local_gpio_pin(pinNumber), 0); k_timer_start(timer, timeout, timeout); } void noTone(pin_size_t pinNumber) { - const struct gpio_dt_spec *spec = &arduino_pins[pinNumber]; - k_timer_stop(&arduino_pin_timers[pinNumber].timer); - gpio_pin_set_dt(spec, 0); + gpio_pin_set(local_gpio_port(pinNumber), local_gpio_pin(pinNumber), 0); } void delay(unsigned long ms) { @@ -402,16 +406,16 @@ void attachInterrupt(pin_size_t pinNumber, voidFuncPtr callback, PinStatus pinSt return; } - pcb = find_gpio_port_callback(arduino_pins[pinNumber].port); + pcb = find_gpio_port_callback(local_gpio_port(pinNumber)); __ASSERT(pcb != nullptr, "gpio_port_callback not found"); - pcb->pins |= BIT(arduino_pins[pinNumber].pin); + pcb->pins |= BIT(local_gpio_pin(pinNumber)); setInterruptHandler(pinNumber, callback); enableInterrupt(pinNumber); - gpio_pin_interrupt_configure(arduino_pins[pinNumber].port, arduino_pins[pinNumber].pin, intmode); + gpio_pin_interrupt_configure(local_gpio_port(pinNumber), local_gpio_pin(pinNumber), intmode); gpio_init_callback(&pcb->callback, handleGpioCallback, pcb->pins); - gpio_add_callback(arduino_pins[pinNumber].port, &pcb->callback); + gpio_add_callback(local_gpio_port(pinNumber), &pcb->callback); } void detachInterrupt(pin_size_t pinNumber) @@ -439,29 +443,30 @@ long random(long max) { #endif unsigned long pulseIn(pin_size_t pinNumber, uint8_t state, unsigned long timeout) { + const struct device* port = local_gpio_port(pinNumber); + const size_t pin = local_gpio_pin(pinNumber); struct k_timer timer; int64_t start, end, delta = 0; - const struct gpio_dt_spec *spec = &arduino_pins[pinNumber]; - if (!gpio_is_ready_dt(spec)) { + if (!device_is_ready(port)) { return 0; } k_timer_init(&timer, NULL, NULL); k_timer_start(&timer, K_MSEC(timeout), K_NO_WAIT); - while(gpio_pin_get_dt(spec) == state && k_timer_status_get(&timer) == 0); + while (gpio_pin_get(port, pin) == state && k_timer_status_get(&timer) == 0); if (k_timer_status_get(&timer) > 0) { goto cleanup; } - while(gpio_pin_get_dt(spec) != state && k_timer_status_get(&timer) == 0); + while (gpio_pin_get(port, pin) != state && k_timer_status_get(&timer) == 0); if (k_timer_status_get(&timer) > 0) { goto cleanup; } start = k_uptime_ticks(); - while(gpio_pin_get_dt(spec) == state && k_timer_status_get(&timer) == 0); + while (gpio_pin_get(port, pin) == state && k_timer_status_get(&timer) == 0); if (k_timer_status_get(&timer) > 0) { goto cleanup; } @@ -475,18 +480,18 @@ unsigned long pulseIn(pin_size_t pinNumber, uint8_t state, unsigned long timeout } void enableInterrupt(pin_size_t pinNumber) { - struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port); + struct gpio_port_callback *pcb = find_gpio_port_callback(local_gpio_port(pinNumber)); if (pcb) { - pcb->handlers[arduino_pins[pinNumber].pin].enabled = true; + pcb->handlers[local_gpio_pin(pinNumber)].enabled = true; } } void disableInterrupt(pin_size_t pinNumber) { - struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port); + struct gpio_port_callback *pcb = find_gpio_port_callback(local_gpio_port(pinNumber)); if (pcb) { - pcb->handlers[arduino_pins[pinNumber].pin].enabled = false; + pcb->handlers[local_gpio_pin(pinNumber)].enabled = false; } } @@ -506,7 +511,7 @@ void noInterrupts(void) { int digitalPinToInterrupt(pin_size_t pin) { struct gpio_port_callback *pcb = - find_gpio_port_callback(arduino_pins[pin].port); + find_gpio_port_callback(local_gpio_port(pin)); return (pcb) ? pin : -1; } diff --git a/documentation/variants.md b/documentation/variants.md index 0ea44c7a1..61c20fb5b 100644 --- a/documentation/variants.md +++ b/documentation/variants.md @@ -90,6 +90,20 @@ uses [the Arduino header definitions](https://github.com/zephyrproject-rtos/zeph }; ``` +### Configure GPIO devices + +The `gpios` node lists the GPIO ports to use. +Pin numbers will be assigned sequentially starting from 0 to the GPIOs of the ports specified here. +For example, if gpio0 and gpio1, each with 16 outputs, are specified, pin 1 of gpio1 will be assigned 17. + +``` +/ { + zephyr,user { + gpios = <&gpio0>, <&gpio1>; + }; +}; +``` + ### Configure Serial devices The `serials` node defines the Serial devices to use. diff --git a/variants/arduino_mkrzero_samd21g18a/arduino_mkrzero_samd21g18a.overlay b/variants/arduino_mkrzero_samd21g18a/arduino_mkrzero_samd21g18a.overlay index 4e69fbc92..89869442f 100644 --- a/variants/arduino_mkrzero_samd21g18a/arduino_mkrzero_samd21g18a.overlay +++ b/variants/arduino_mkrzero_samd21g18a/arduino_mkrzero_samd21g18a.overlay @@ -54,6 +54,7 @@ <&adc 6>, <&adc 7>; + gpio-ports = <&porta>, <&portb>; serials = <&sercom5>; i2cs = <&sercom0>; }; diff --git a/variants/arduino_nano_33_ble_nrf52840/arduino_nano_33_ble_nrf52840.overlay b/variants/arduino_nano_33_ble_nrf52840/arduino_nano_33_ble_nrf52840.overlay index 6c8f9754d..3e4bb1801 100644 --- a/variants/arduino_nano_33_ble_nrf52840/arduino_nano_33_ble_nrf52840.overlay +++ b/variants/arduino_nano_33_ble_nrf52840/arduino_nano_33_ble_nrf52840.overlay @@ -59,6 +59,7 @@ <&adc 4>, <&adc 1>; + gpio-ports = <&gpio0>, <&gpio1>; serials = <&uart0>; i2cs = <&arduino_nano_i2c>; }; diff --git a/variants/arduino_nano_33_ble_nrf52840_sense/arduino_nano_33_ble_nrf52840_sense.overlay b/variants/arduino_nano_33_ble_nrf52840_sense/arduino_nano_33_ble_nrf52840_sense.overlay index 6c8f9754d..3e4bb1801 100644 --- a/variants/arduino_nano_33_ble_nrf52840_sense/arduino_nano_33_ble_nrf52840_sense.overlay +++ b/variants/arduino_nano_33_ble_nrf52840_sense/arduino_nano_33_ble_nrf52840_sense.overlay @@ -59,6 +59,7 @@ <&adc 4>, <&adc 1>; + gpio-ports = <&gpio0>, <&gpio1>; serials = <&uart0>; i2cs = <&arduino_nano_i2c>; }; diff --git a/variants/arduino_nano_33_iot_samd21g18a/arduino_nano_33_iot_samd21g18a.overlay b/variants/arduino_nano_33_iot_samd21g18a/arduino_nano_33_iot_samd21g18a.overlay index d99109799..c547dbdfe 100644 --- a/variants/arduino_nano_33_iot_samd21g18a/arduino_nano_33_iot_samd21g18a.overlay +++ b/variants/arduino_nano_33_iot_samd21g18a/arduino_nano_33_iot_samd21g18a.overlay @@ -60,6 +60,7 @@ <&adc 6>, <&adc 7>; + gpio-ports = <&porta>, <&portb>; serials = <&sercom5>; i2cs = <&arduino_nano_i2c>; }; diff --git a/variants/beagleconnect_freedom_cc1352p7/beagleconnect_freedom_cc1352p7.overlay b/variants/beagleconnect_freedom_cc1352p7/beagleconnect_freedom_cc1352p7.overlay index f4061d46c..e434d9b50 100644 --- a/variants/beagleconnect_freedom_cc1352p7/beagleconnect_freedom_cc1352p7.overlay +++ b/variants/beagleconnect_freedom_cc1352p7/beagleconnect_freedom_cc1352p7.overlay @@ -58,6 +58,8 @@ <&gpio0 28 GPIO_ACTIVE_HIGH>; /* D3 - MB1 CS - A5 */ builtin-led-gpios = <&gpio0 18 GPIO_ACTIVE_HIGH>; /* 2.4GHz TX/RX */ + + gpio-ports = <&gpio0>; serials = <&uart0 &uart1>; i2cs = <&i2c0>; spis = <&spi0>; diff --git a/variants/cc3220sf_launchxl_cc3220sf/cc3220sf_launchxl_cc3220sf.overlay b/variants/cc3220sf_launchxl_cc3220sf/cc3220sf_launchxl_cc3220sf.overlay index f1c91f6d2..658c22cb9 100644 --- a/variants/cc3220sf_launchxl_cc3220sf/cc3220sf_launchxl_cc3220sf.overlay +++ b/variants/cc3220sf_launchxl_cc3220sf/cc3220sf_launchxl_cc3220sf.overlay @@ -30,6 +30,8 @@ <&boosterpack_header 31 0>, /* GPIO_24 */ <&boosterpack_header 32 0>; /* GPIO_23 */ builtin-led-gpios = <&boosterpack_header 10 0>; /* GREEN_LED */ + + gpio-ports = <&gpioa0>, <&gpioa1>, <&gpioa2>, <&gpioa3>; serials = <&boosterpack_serial>; i2cs = <&boosterpack_i2c>; }; diff --git a/variants/cc3220sf_launchxl_cc3220sf/variant.h b/variants/cc3220sf_launchxl_cc3220sf/variant.h index 0be70fc91..6dcb3e81e 100644 --- a/variants/cc3220sf_launchxl_cc3220sf/variant.h +++ b/variants/cc3220sf_launchxl_cc3220sf/variant.h @@ -7,8 +7,8 @@ /* All the pins that are 100 + x are gpio1 pins and < 100 are in gpio0 */ #pragma once -#define LED_BUILTIN 4 -#define YELLOW_LED 3 -#define GREEN_LED 4 -#define RED_LED 19 +#define LED_BUILTIN D4 +#define YELLOW_LED D3 +#define GREEN_LED D4 +#define RED_LED D19 diff --git a/variants/nrf52840dk_nrf52840/nrf52840dk_nrf52840.overlay b/variants/nrf52840dk_nrf52840/nrf52840dk_nrf52840.overlay index 220208215..e0ff9ae26 100644 --- a/variants/nrf52840dk_nrf52840/nrf52840dk_nrf52840.overlay +++ b/variants/nrf52840dk_nrf52840/nrf52840dk_nrf52840.overlay @@ -52,6 +52,8 @@ <&arduino_adc 3>, <&arduino_adc 4>, <&arduino_adc 5>; + + gpio-ports = <&gpio0>, <&gpio1>; }; }; diff --git a/variants/nrf9160dk_nrf9160/nrf9160dk_nrf9160.overlay b/variants/nrf9160dk_nrf9160/nrf9160dk_nrf9160.overlay index d69fdcb5f..63a175089 100644 --- a/variants/nrf9160dk_nrf9160/nrf9160dk_nrf9160.overlay +++ b/variants/nrf9160dk_nrf9160/nrf9160dk_nrf9160.overlay @@ -57,6 +57,8 @@ <&arduino_adc 3>, <&arduino_adc 4>, <&arduino_adc 5>; + + gpio-ports = <&gpio0>; }; }; diff --git a/variants/rpi_pico_rp2040/rpi_pico_rp2040.overlay b/variants/rpi_pico_rp2040/rpi_pico_rp2040.overlay index 92baee3bf..77f003131 100644 --- a/variants/rpi_pico_rp2040/rpi_pico_rp2040.overlay +++ b/variants/rpi_pico_rp2040/rpi_pico_rp2040.overlay @@ -78,6 +78,7 @@ <&adc 1>, <&adc 2>; + gpio-ports = <&gpio0>; serials = <&pico_serial>; i2cs = <&pico_i2c0>; spis = <&pico_spi>; From 934a931f81dc48693e53fe2031e2addc6a5cbb09 Mon Sep 17 00:00:00 2001 From: TOKITA Hiroshi Date: Sun, 31 Aug 2025 08:59:26 +0900 Subject: [PATCH 2/3] Arduino.h: Remove `builtin_led_gpios` rule Now that GPIO can be specified generically, we will discontinue the definition generation of LED_BUILTIN from builtin_led_gpios. Delete this definition where automatic generation from led0 is not an issue, and define it in variant.h in all other cases. Signed-off-by: TOKITA Hiroshi --- cores/arduino/Arduino.h | 7 +---- documentation/variants.md | 27 +++---------------- .../arduino_nano_33_ble_nrf52840.overlay | 2 -- .../arduino_nano_33_ble_nrf52840/variant.h | 4 +++ ...arduino_nano_33_ble_nrf52840_sense.overlay | 2 -- .../variant.h | 4 +++ .../beagleconnect_freedom_cc1352p7.overlay | 2 -- .../cc3220sf_launchxl_cc3220sf.overlay | 1 - .../rpi_pico_rp2040/rpi_pico_rp2040.overlay | 2 -- 9 files changed, 13 insertions(+), 38 deletions(-) diff --git a/cores/arduino/Arduino.h b/cores/arduino/Arduino.h index 78126673f..c48f69d23 100644 --- a/cores/arduino/Arduino.h +++ b/cores/arduino/Arduino.h @@ -49,13 +49,8 @@ int digitalPinToInterrupt(pin_size_t pin); #include -#ifndef LED_BUILTIN -#if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), builtin_led_gpios) \ - && (DT_PROP_LEN(DT_PATH(zephyr_user), builtin_led_gpios) > 0) -#define LED_BUILTIN ZARD_GLOBAL_GPIO_NUM(DT_PATH(zephyr_user), builtin_led_gpios, 0) -#elif DT_NODE_EXISTS(DT_ALIAS(led0)) +#if !defined(LED_BUILTIN) && DT_NODE_EXISTS(DT_ALIAS(led0)) #define LED_BUILTIN ZARD_GLOBAL_GPIO_NUM(DT_ALIAS(led0), gpios, 0) -#endif #endif // LED_BUILTIN #ifdef __cplusplus diff --git a/documentation/variants.md b/documentation/variants.md index 61c20fb5b..4ef6c1619 100644 --- a/documentation/variants.md +++ b/documentation/variants.md @@ -151,31 +151,12 @@ The following example instantiates `Wire` and `Wire2` with each `i2c0` and `i2c1 ### Configure Builtin-LED -The `builtin-led-gpios` node defines the Builtin-LED. -This node defines the `LED_BUILTIN` value by looking up the `digital-pin-gpios` -array to find the index of the pin. +If `LED_BUILTIN` is defined, it will take precedence. +This is usually defined in each board's variant.h file. -The node is phandle-array, which uses the format same as `digital-pin-gpios`. +If the `LED_BUILTIN` is not defined and the LED node aliased as `led0` available, +`LED_BUILTIN` referencing `led0` will be automatically defined. -It set the digital pin number to the `LED_BUILTIN` if found the pin -that defined in `builtin-led-gpios` from `digital-pin-gpios`. - -If the `builtin-led-gpios` is not defined, Use the node aliased as `led0` -to define `LED_BUILTIN`. - -The `LED_BUILTIN` does not define here if it has not found both nodes or -defined `LED_BUILTIN` already. - -For example, in the case of the 13th digital pins connected to the onboard LED, -define `builtin-led-gpios` as follows. - -``` -/ { - zephyr,user { - builtin-led-gpios = <&arduino_nano_header 13 0>; - }; -}; -``` ### Overlays from scratch diff --git a/variants/arduino_nano_33_ble_nrf52840/arduino_nano_33_ble_nrf52840.overlay b/variants/arduino_nano_33_ble_nrf52840/arduino_nano_33_ble_nrf52840.overlay index 3e4bb1801..1398675a1 100644 --- a/variants/arduino_nano_33_ble_nrf52840/arduino_nano_33_ble_nrf52840.overlay +++ b/variants/arduino_nano_33_ble_nrf52840/arduino_nano_33_ble_nrf52840.overlay @@ -40,8 +40,6 @@ <&arduino_nano_header 20 0>, <&arduino_nano_header 21 0>; - builtin-led-gpios = <&arduino_nano_header 13 0>; - pwms = <&pwm1 1 255 PWM_POLARITY_NORMAL>, <&pwm1 2 255 PWM_POLARITY_NORMAL>, <&pwm1 3 255 PWM_POLARITY_NORMAL>, diff --git a/variants/arduino_nano_33_ble_nrf52840/variant.h b/variants/arduino_nano_33_ble_nrf52840/variant.h index 06cab2dae..26cb76aad 100644 --- a/variants/arduino_nano_33_ble_nrf52840/variant.h +++ b/variants/arduino_nano_33_ble_nrf52840/variant.h @@ -3,3 +3,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ + +#pragma once + +#define LED_BUILTIN D13 diff --git a/variants/arduino_nano_33_ble_nrf52840_sense/arduino_nano_33_ble_nrf52840_sense.overlay b/variants/arduino_nano_33_ble_nrf52840_sense/arduino_nano_33_ble_nrf52840_sense.overlay index 3e4bb1801..1398675a1 100644 --- a/variants/arduino_nano_33_ble_nrf52840_sense/arduino_nano_33_ble_nrf52840_sense.overlay +++ b/variants/arduino_nano_33_ble_nrf52840_sense/arduino_nano_33_ble_nrf52840_sense.overlay @@ -40,8 +40,6 @@ <&arduino_nano_header 20 0>, <&arduino_nano_header 21 0>; - builtin-led-gpios = <&arduino_nano_header 13 0>; - pwms = <&pwm1 1 255 PWM_POLARITY_NORMAL>, <&pwm1 2 255 PWM_POLARITY_NORMAL>, <&pwm1 3 255 PWM_POLARITY_NORMAL>, diff --git a/variants/arduino_nano_33_ble_nrf52840_sense/variant.h b/variants/arduino_nano_33_ble_nrf52840_sense/variant.h index 06cab2dae..26cb76aad 100644 --- a/variants/arduino_nano_33_ble_nrf52840_sense/variant.h +++ b/variants/arduino_nano_33_ble_nrf52840_sense/variant.h @@ -3,3 +3,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ + +#pragma once + +#define LED_BUILTIN D13 diff --git a/variants/beagleconnect_freedom_cc1352p7/beagleconnect_freedom_cc1352p7.overlay b/variants/beagleconnect_freedom_cc1352p7/beagleconnect_freedom_cc1352p7.overlay index e434d9b50..a89b2ce8f 100644 --- a/variants/beagleconnect_freedom_cc1352p7/beagleconnect_freedom_cc1352p7.overlay +++ b/variants/beagleconnect_freedom_cc1352p7/beagleconnect_freedom_cc1352p7.overlay @@ -57,8 +57,6 @@ <&gpio0 27 GPIO_ACTIVE_HIGH>, /* D7 - MB2 CS - A4 */ <&gpio0 28 GPIO_ACTIVE_HIGH>; /* D3 - MB1 CS - A5 */ - builtin-led-gpios = <&gpio0 18 GPIO_ACTIVE_HIGH>; /* 2.4GHz TX/RX */ - gpio-ports = <&gpio0>; serials = <&uart0 &uart1>; i2cs = <&i2c0>; diff --git a/variants/cc3220sf_launchxl_cc3220sf/cc3220sf_launchxl_cc3220sf.overlay b/variants/cc3220sf_launchxl_cc3220sf/cc3220sf_launchxl_cc3220sf.overlay index 658c22cb9..366936c4c 100644 --- a/variants/cc3220sf_launchxl_cc3220sf/cc3220sf_launchxl_cc3220sf.overlay +++ b/variants/cc3220sf_launchxl_cc3220sf/cc3220sf_launchxl_cc3220sf.overlay @@ -29,7 +29,6 @@ <&boosterpack_header 30 0>, /* GPIO_00 */ <&boosterpack_header 31 0>, /* GPIO_24 */ <&boosterpack_header 32 0>; /* GPIO_23 */ - builtin-led-gpios = <&boosterpack_header 10 0>; /* GREEN_LED */ gpio-ports = <&gpioa0>, <&gpioa1>, <&gpioa2>, <&gpioa3>; serials = <&boosterpack_serial>; diff --git a/variants/rpi_pico_rp2040/rpi_pico_rp2040.overlay b/variants/rpi_pico_rp2040/rpi_pico_rp2040.overlay index 77f003131..d51c154fa 100644 --- a/variants/rpi_pico_rp2040/rpi_pico_rp2040.overlay +++ b/variants/rpi_pico_rp2040/rpi_pico_rp2040.overlay @@ -38,8 +38,6 @@ <&pico_header 27 0>, <&pico_header 28 0>; - builtin-led-gpios = <&gpio0 25 0>; - pwm-pin-gpios = <&pico_header 2 0>, <&pico_header 3 0>, <&pico_header 7 0>, From b398bfae05e8cce37d32be7787b5d310811a8bd3 Mon Sep 17 00:00:00 2001 From: TOKITA Hiroshi Date: Wed, 20 Aug 2025 20:48:15 +0900 Subject: [PATCH 3/3] zephyrCommon: Improved interrupt handling - The structure has been revised and unnecessary fields have been removed. - Interrupt masks are now directly modified by changing the pin_mask parameter in `struct gpio_callback`. - Renamed non-Arduino-derived `setInterruptHandler` and `handleGpioCallback` functions to Zephyr-like names. Signed-off-by: TOKITA Hiroshi --- cores/arduino/zephyrCommon.cpp | 53 ++++++++++++++-------------------- 1 file changed, 21 insertions(+), 32 deletions(-) diff --git a/cores/arduino/zephyrCommon.cpp b/cores/arduino/zephyrCommon.cpp index ac62d9970..90887e510 100644 --- a/cores/arduino/zephyrCommon.cpp +++ b/cores/arduino/zephyrCommon.cpp @@ -87,26 +87,15 @@ constexpr int max_ngpios = max_in_list( * GPIO callback implementation */ -struct arduino_callback { - voidFuncPtr handler; - bool enabled; -}; - struct gpio_port_callback { struct gpio_callback callback; - struct arduino_callback handlers[max_ngpios]; - gpio_port_pins_t pins; - const struct device *dev; + voidFuncPtr handlers[max_ngpios]; } port_callback[ARRAY_SIZE(gpios)]; struct gpio_port_callback *find_gpio_port_callback(const struct device *dev) { - for (size_t i = 0; i < ARRAY_SIZE(port_callback); i++) { - if (port_callback[i].dev == dev) { - return &port_callback[i]; - } - if (port_callback[i].dev == nullptr) { - port_callback[i].dev = dev; + for (size_t i = 0; i < ARRAY_SIZE(gpios); i++) { + if (dev == gpios[i]) { return &port_callback[i]; } } @@ -114,22 +103,20 @@ struct gpio_port_callback *find_gpio_port_callback(const struct device *dev) return nullptr; } -void setInterruptHandler(pin_size_t pinNumber, voidFuncPtr func) -{ +void set_interrupt_handler(pin_size_t pinNumber, voidFuncPtr func) { struct gpio_port_callback *pcb = find_gpio_port_callback(local_gpio_port(pinNumber)); if (pcb) { - pcb->handlers[local_gpio_pin(pinNumber)].handler = func; + pcb->handlers[local_gpio_pin(pinNumber)] = func; } } -void handleGpioCallback(const struct device *port, struct gpio_callback *cb, uint32_t pins) -{ - struct gpio_port_callback *pcb = (struct gpio_port_callback *)cb; +void handle_gpio_callback(const struct device *port, struct gpio_callback *cb, uint32_t pins) { + struct gpio_port_callback *pcb = CONTAINER_OF(cb, struct gpio_port_callback, callback); for (uint32_t i = 0; i < max_ngpios; i++) { - if (pins & BIT(i) && pcb->handlers[i].enabled) { - pcb->handlers[i].handler(); + if (pins & BIT(i) && pcb->handlers[i]) { + pcb->handlers[i](); } } } @@ -247,8 +234,7 @@ void tone_expiry_cb(struct k_timer *timer) { } } -void tone(pin_size_t pinNumber, unsigned int frequency, - unsigned long duration) { +void tone(pin_size_t pinNumber, unsigned int frequency, unsigned long duration) { struct k_timer *timer; k_timeout_t timeout; @@ -409,19 +395,22 @@ void attachInterrupt(pin_size_t pinNumber, voidFuncPtr callback, PinStatus pinSt pcb = find_gpio_port_callback(local_gpio_port(pinNumber)); __ASSERT(pcb != nullptr, "gpio_port_callback not found"); - pcb->pins |= BIT(local_gpio_pin(pinNumber)); - setInterruptHandler(pinNumber, callback); - enableInterrupt(pinNumber); + set_interrupt_handler(pinNumber, callback); + if (pcb->callback.handler == NULL) { + gpio_init_callback(&pcb->callback, handle_gpio_callback, 0); + gpio_add_callback(local_gpio_port(pinNumber), &pcb->callback); + } + + enableInterrupt(pinNumber); gpio_pin_interrupt_configure(local_gpio_port(pinNumber), local_gpio_pin(pinNumber), intmode); - gpio_init_callback(&pcb->callback, handleGpioCallback, pcb->pins); - gpio_add_callback(local_gpio_port(pinNumber), &pcb->callback); } void detachInterrupt(pin_size_t pinNumber) { - setInterruptHandler(pinNumber, nullptr); + gpio_pin_interrupt_configure(local_gpio_port(pinNumber), local_gpio_pin(pinNumber), 0); disableInterrupt(pinNumber); + set_interrupt_handler(pinNumber, nullptr); } #ifndef CONFIG_MINIMAL_LIBC_RAND @@ -483,7 +472,7 @@ void enableInterrupt(pin_size_t pinNumber) { struct gpio_port_callback *pcb = find_gpio_port_callback(local_gpio_port(pinNumber)); if (pcb) { - pcb->handlers[local_gpio_pin(pinNumber)].enabled = true; + pcb->callback.pin_mask |= BIT(local_gpio_pin(pinNumber)); } } @@ -491,7 +480,7 @@ void disableInterrupt(pin_size_t pinNumber) { struct gpio_port_callback *pcb = find_gpio_port_callback(local_gpio_port(pinNumber)); if (pcb) { - pcb->handlers[local_gpio_pin(pinNumber)].enabled = false; + pcb->callback.pin_mask &= ~BIT(local_gpio_pin(pinNumber)); } }