Skip to content

Commit 769f878

Browse files
committed
cores: arduino: zephyrCommon: Generate config from connector definition
If digital-gpio-pins is not defined, the pin configuration will be generated using the connector definition. This allows ArduinoCore-Zephyr to be used on boards that have arduino-header defined, without requiring specific configuration in ArduinoCore-Zephyr. Signed-off-by: TOKITA Hiroshi <tokita.hiroshi@gmail.com>
1 parent 1105639 commit 769f878

File tree

2 files changed

+186
-6
lines changed

2 files changed

+186
-6
lines changed

cores/arduino/Arduino.h

Lines changed: 77 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
* Copyright (c) 2022 Dhruva Gole
3+
* Copyright (c) 2026 TOKITA Hiroshi
34
*
45
* SPDX-License-Identifier: Apache-2.0
56
*/
@@ -14,6 +15,7 @@
1415
#include <zephyr/drivers/adc.h>
1516
#include <zephyr/drivers/i2c.h>
1617

18+
#if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), digital_pin_gpios)
1719
#define DIGITAL_PIN_EXISTS(n, p, i, dev, num) \
1820
(((dev == DT_REG_ADDR(DT_PHANDLE_BY_IDX(n, p, i))) && \
1921
(num == DT_PHA_BY_IDX(n, p, i, pin))) \
@@ -74,12 +76,78 @@
7476

7577
#define DN_ENUMS(n, p, i) D##i = i
7678

79+
#else
80+
81+
#if DT_NODE_EXISTS(DT_NODELABEL(arduino_header))
82+
#define ZARD_CONNECTOR arduino_header
83+
#elif DT_NODE_EXISTS(DT_NODELABEL(arduino_mkr_header))
84+
#define ZARD_CONNECTOR arduino_mkr_header
85+
#elif DT_NODE_EXISTS(DT_NODELABEL(arduino_nano_header))
86+
#define ZARD_CONNECTOR arduino_nano_header
87+
#elif DT_NODE_EXISTS(DT_NODELABEL(pico_header))
88+
#define ZARD_CONNECTOR pico_header
89+
#elif DT_NODE_EXISTS(DT_NODELABEL(boosterpack_header))
90+
#define ZARD_CONNECTOR boosterpack_header
91+
#endif
92+
93+
#if DT_NODE_EXISTS(DT_NODELABEL(arduino_adc))
94+
#define ZARD_ADC_CONNECTOR arduino_adc
95+
#endif
96+
97+
#if DT_NODE_EXISTS(DT_NODELABEL(arduino_pwm))
98+
#define ZARD_PWM_CONNECTOR arduino_pwm
99+
#endif
100+
101+
#define ZARD_CHECK_GPIO_CTLR_OKAY(node_id) \
102+
COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(node_id), \
103+
(COND_CODE_1(DT_NODE_HAS_PROP(node_id, gpio_controller), (node_id,), ())), ())
104+
105+
#define ZARD_ALL_OKAY_GPIO_CTLR \
106+
GET_ARGS_FIRST_N(NUM_VA_ARGS_LESS_1(DT_FOREACH_NODE(ZARD_CHECK_GPIO_CTLR_OKAY)), \
107+
DT_FOREACH_NODE(ZARD_CHECK_GPIO_CTLR_OKAY))
108+
109+
#define ZARD_IDX_IF_MATCH(i, n) \
110+
COND_CODE_1(DT_SAME_NODE(n, GET_ARG_N(UTIL_INC(i), ZARD_ALL_OKAY_GPIO_CTLR)), (i), ())
111+
112+
#define ZARD_MATCH_IDX(n) \
113+
LISTIFY(NUM_VA_ARGS_LESS_1(ZARD_ALL_OKAY_GPIO_CTLR), ZARD_IDX_IF_MATCH, (), n)
114+
115+
#define ZARD_GET_NGPIOS(i, ...) DT_PROP(GET_ARG_N(UTIL_INC(i), __VA_ARGS__), ngpios)
116+
#define ZARD_SUM_NGPIOS(...) \
117+
LISTIFY(NUM_VA_ARGS_LESS_1(__VA_ARGS__), ZARD_GET_NGPIOS, (+), __VA_ARGS__)
118+
#define ZARD_GLOBAL_GPIO_NUM_(ph) \
119+
ZARD_SUM_NGPIOS(GET_ARGS_FIRST_N(ZARD_MATCH_IDX(ph), ZARD_ALL_OKAY_GPIO_CTLR))
120+
121+
#define ZARD_GLOBAL_GPIO_NUM(ph) COND_CODE_1(IS_EQ(NUM_VA_ARGS(ZARD_GLOBAL_GPIO_NUM_(ph)), 0), \
122+
(0), (ZARD_GLOBAL_GPIO_NUM_(ph)))
123+
124+
#define ZARD_CONN_DN_ENUMS(n, p, i) \
125+
UTIL_CAT(D, DT_MAP_ENTRY_CHILD_SPECIFIER_BY_IDX(n, p, i, 0)) = \
126+
ZARD_GLOBAL_GPIO_NUM(DT_MAP_ENTRY_PARENT_BY_IDX(n, p, i)) + \
127+
DT_MAP_ENTRY_PARENT_SPECIFIER_BY_IDX(n, p, i, 0)
128+
129+
#define ZARD_CONN_AN_ENUMS(n, p, i) \
130+
UTIL_CAT(A, DT_MAP_ENTRY_CHILD_SPECIFIER_BY_IDX(n, p, i, 0)) = \
131+
ZARD_GLOBAL_GPIO_NUM(DT_MAP_ENTRY_PARENT_BY_IDX( \
132+
DT_NODELABEL(ZARD_CONNECTOR), gpio_map, i)) + \
133+
DT_MAP_ENTRY_PARENT_SPECIFIER_BY_IDX(DT_NODELABEL(ZARD_CONNECTOR), gpio_map, i, 0)
134+
135+
#if DT_NODE_EXISTS(DT_ALIAS(led0))
136+
#define LED_BUILTIN_ ZARD_GLOBAL_GPIO_NUM(DT_PHANDLE_BY_IDX(DT_ALIAS(led0), gpios, 0)) + \
137+
DT_PHA_BY_IDX(DT_ALIAS(led0), gpios, 0, pin)
138+
#endif
139+
#endif
140+
77141
/*
78142
* expand as
79143
* enum digitalPins { D0, D1, ... LED... NUM_OF_DIGITAL_PINS };
80144
*/
81145
enum digitalPins {
146+
#if DT_PROP_LEN_OR(DT_PATH(zephyr_user), digital_pin_gpios, 0) > 0
82147
DT_FOREACH_PROP_ELEM_SEP(DT_PATH(zephyr_user), digital_pin_gpios, DN_ENUMS, (, )),
148+
#elif defined(ZARD_CONNECTOR)
149+
DT_FOREACH_MAP_ENTRY_SEP(DT_NODELABEL(ZARD_CONNECTOR), gpio_map, ZARD_CONN_DN_ENUMS, (,)),
150+
#endif
83151
NUM_OF_DIGITAL_PINS
84152
};
85153

@@ -88,8 +156,15 @@ enum digitalPins {
88156
#define AN_ENUMS(n, p, i) A ## i = DIGITAL_PIN_GPIOS_FIND_PIN( \
89157
DT_REG_ADDR(DT_PHANDLE_BY_IDX(DT_PATH(zephyr_user), p, i)), \
90158
DT_PHA_BY_IDX(DT_PATH(zephyr_user), p, i, pin)),
91-
enum analogPins { DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user),
92-
adc_pin_gpios, AN_ENUMS) };
159+
enum analogPins {
160+
#if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), adc_pin_gpios)
161+
DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), adc_pin_gpios, AN_ENUMS)
162+
#elif defined(ZARD_ADC_CONNECTOR)
163+
DT_FOREACH_MAP_ENTRY_SEP(DT_NODELABEL(ZARD_ADC_CONNECTOR), io_channel_map,
164+
ZARD_CONN_AN_ENUMS, (,)),
165+
#endif
166+
NUM_OF_ANALOG_PINS
167+
};
93168

94169
#endif
95170

cores/arduino/zephyrCommon.cpp

Lines changed: 109 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,34 @@
11
/*
22
* Copyright (c) 2022 Dhruva Gole
3+
* Copyright (c) 2026 TOKITA Hiroshi
34
*
45
* SPDX-License-Identifier: Apache-2.0
56
*/
67

78
#include <Arduino.h>
89
#include "zephyrInternal.h"
910

11+
#if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), digital_pin_gpios)
1012
static constexpr struct gpio_dt_spec arduino_pins[] = {DT_FOREACH_PROP_ELEM_SEP(
1113
DT_PATH(zephyr_user), digital_pin_gpios, GPIO_DT_SPEC_GET_BY_IDX, (, ))};
14+
#else
15+
#define GET_GPIO_DEVICES(node_id) \
16+
COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(node_id), \
17+
(COND_CODE_1(DT_NODE_HAS_PROP(node_id, gpio_controller), \
18+
(DEVICE_DT_GET(node_id),), ())), ())
19+
20+
#define GET_GPIO_NGPIOS(node_id) \
21+
COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(node_id), \
22+
(COND_CODE_1(DT_NODE_HAS_PROP(node_id, gpio_controller), \
23+
(DT_PROP(node_id, ngpios),), ())), ())
24+
25+
static constexpr const struct device *gpio_ports[] = {
26+
DT_FOREACH_NODE(GET_GPIO_DEVICES)
27+
};
28+
static constexpr uint32_t gpio_ngpios[] = {
29+
DT_FOREACH_NODE(GET_GPIO_NGPIOS)
30+
};
31+
#endif
1232

1333
namespace {
1434

@@ -56,18 +76,77 @@ constexpr const size_t is_first_appearance(const size_t &idx, const size_t &at,
5676
tail...);
5777
}
5878

79+
#if !DT_NODE_HAS_PROP(DT_PATH(zephyr_user), digital_pin_gpios)
80+
constexpr inline const struct device *local_gpio_port(pin_size_t gpin);
81+
82+
constexpr inline const struct device *local_gpio_port_r(pin_size_t pin,
83+
const struct device *const *ctrl,
84+
const uint32_t accum,
85+
const uint32_t *end, size_t n) {
86+
return (n == 0)
87+
? nullptr
88+
: (pin < accum + end[0])
89+
? ctrl[0]
90+
: local_gpio_port_r(pin, ctrl + 1, accum + end[0], end + 1, n - 1);
91+
}
92+
93+
constexpr inline size_t port_index_r(const struct device *target,
94+
const struct device *const *table, pin_size_t idx, size_t n) {
95+
return (n == 0)
96+
? size_t(-1)
97+
: (target == table[0])
98+
? idx
99+
: port_index_r(target, table + 1, idx + 1, n - 1);
100+
}
101+
102+
103+
constexpr inline pin_size_t port_idx(pin_size_t gpin) {
104+
return port_index_r(local_gpio_port(gpin), gpio_ports, 0, ARRAY_SIZE(gpio_ports));
105+
}
106+
107+
constexpr inline pin_size_t end_accum_r(const uint32_t accum, const uint32_t *end, size_t n) {
108+
return (n == 0) ? accum : end_accum_r(accum + end[0], end + 1, n - 1);
109+
}
110+
111+
constexpr inline pin_size_t end_accum(size_t n) {
112+
return end_accum_r(0, gpio_ngpios, n);
113+
}
114+
115+
constexpr inline pin_size_t global_gpio_pin_(size_t port_idx, pin_size_t lpin) {
116+
return port_idx == size_t(-1) ? size_t(-1) : end_accum(port_idx) + lpin;
117+
}
118+
119+
constexpr inline pin_size_t global_gpio_pin(const struct device *lport, pin_size_t lpin) {
120+
return global_gpio_pin_(port_index_r(lport, gpio_ports, 0, ARRAY_SIZE(gpio_ports)), lpin);
121+
}
122+
#endif
123+
59124
constexpr inline const struct device *local_gpio_port(pin_size_t gpin) {
125+
#if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), digital_pin_gpios)
60126
return arduino_pins[gpin].port;
127+
#else
128+
return local_gpio_port_r(gpin, gpio_ports, 0, gpio_ngpios, ARRAY_SIZE(gpio_ports));
129+
#endif
61130
}
62131

63132
constexpr inline pin_size_t local_gpio_pin(pin_size_t gpin) {
133+
#if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), digital_pin_gpios)
64134
return arduino_pins[gpin].pin;
135+
#else
136+
return port_idx(gpin) == pin_size_t(-1) ? pin_size_t(-1) : gpin - end_accum(port_idx(gpin));
137+
#endif
65138
}
66139

67140
inline int global_gpio_pin_configure(pin_size_t pinNumber, int flags) {
141+
#if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), digital_pin_gpios)
68142
return gpio_pin_configure_dt(&arduino_pins[pinNumber], flags);
143+
#else
144+
return gpio_pin_configure(local_gpio_port(pinNumber), local_gpio_pin(pinNumber), flags);
145+
#endif
69146
}
70147

148+
#if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), digital_pin_gpios)
149+
#if DT_PROP_LEN_OR(DT_PATH(zephyr_user), digital_pin_gpios, 0) > 0
71150
#define GET_DEVICE_VARGS(n, p, i, _) DEVICE_DT_GET(DT_GPIO_CTLR_BY_IDX(n, p, i))
72151
#define FIRST_APPEARANCE(n, p, i) \
73152
is_first_appearance(0, i, ((size_t)-1), DEVICE_DT_GET(DT_GPIO_CTLR_BY_IDX(n, p, i)), \
@@ -79,6 +158,14 @@ const int port_num =
79158
#define GPIO_NGPIOS(n, p, i) DT_PROP(DT_GPIO_CTLR_BY_IDX(n, p, i), ngpios)
80159
const int max_ngpios = max_in_list(
81160
0, DT_FOREACH_PROP_ELEM_SEP(DT_PATH(zephyr_user), digital_pin_gpios, GPIO_NGPIOS, (, )));
161+
#else
162+
const int port_num = 1;
163+
const int max_ngpios = 0;
164+
#endif
165+
#else
166+
const int port_num = ARRAY_SIZE(gpio_ports);
167+
const int max_ngpios = max_in_list( DT_FOREACH_NODE(GET_GPIO_NGPIOS) 0);
168+
#endif
82169

83170
/*
84171
* GPIO callback implementation
@@ -138,13 +225,19 @@ void handleGpioCallback(const struct device *port, struct gpio_callback *cb, uin
138225
DIGITAL_PIN_GPIOS_FIND_PIN( \
139226
DT_REG_ADDR(DT_PHANDLE_BY_IDX(DT_PATH(zephyr_user), p, i)), \
140227
DT_PHA_BY_IDX(DT_PATH(zephyr_user), p, i, pin)),
228+
#define PWM_CONN_PINNUM(n, p, i) DT_MAP_ENTRY_CHILD_SPECIFIER_BY_IDX(n, p, i, 0)
141229

142230
const struct pwm_dt_spec arduino_pwm[] =
143231
{ DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), pwms, PWM_DT_SPEC) };
144232

145233
/* pwm-pins node provides a mapping digital pin numbers to pwm channels */
146-
const pin_size_t arduino_pwm_pins[] =
147-
{ DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), pwm_pin_gpios, PWM_PINS) };
234+
const pin_size_t arduino_pwm_pins[] = {
235+
#if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), pwm_pin_gpios)
236+
DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), pwm_pin_gpios, PWM_PINS)
237+
#else
238+
DT_FOREACH_MAP_ENTRY_SEP(DT_NODELABEL(ZARD_PWM_CONNECTOR), pwm_map, PWM_CONN_PINNUM, (, ))
239+
#endif
240+
};
148241

149242
size_t pwm_pin_index(pin_size_t pinNumber) {
150243
for(size_t i=0; i<ARRAY_SIZE(arduino_pwm_pins); i++) {
@@ -165,13 +258,19 @@ size_t pwm_pin_index(pin_size_t pinNumber) {
165258
DT_REG_ADDR(DT_PHANDLE_BY_IDX(DT_PATH(zephyr_user), p, i)), \
166259
DT_PHA_BY_IDX(DT_PATH(zephyr_user), p, i, pin)),
167260
#define ADC_CH_CFG(n,p,i) arduino_adc[i].channel_cfg,
261+
#define ADC_CONN_PINNUM(n, p, i) DT_MAP_ENTRY_CHILD_SPECIFIER_BY_IDX(n, p, i, 0)
168262

169263
const struct adc_dt_spec arduino_adc[] =
170264
{ DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), io_channels, ADC_DT_SPEC) };
171265

172266
/* io-channel-pins node provides a mapping digital pin numbers to adc channels */
173-
const pin_size_t arduino_analog_pins[] =
174-
{ DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), adc_pin_gpios, ADC_PINS) };
267+
const pin_size_t arduino_analog_pins[] = {
268+
#if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), adc_pin_gpios)
269+
DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), adc_pin_gpios, ADC_PINS)
270+
#else
271+
DT_FOREACH_MAP_ENTRY_SEP(DT_NODELABEL(ZARD_ADC_CONNECTOR), io_channel_map, ADC_CONN_PINNUM, (,))
272+
#endif
273+
};
175274

176275
struct adc_channel_cfg channel_cfg[ARRAY_SIZE(arduino_analog_pins)] =
177276
{ DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), io_channels, ADC_CH_CFG) };
@@ -225,7 +324,13 @@ PinStatus digitalRead(pin_size_t pinNumber) {
225324
}
226325

227326
#ifndef MAX_TONE_PINS
327+
#if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), digital_pin_gpios)
228328
#define MAX_TONE_PINS DT_PROP_LEN(DT_PATH(zephyr_user), digital_pin_gpios)
329+
#elif defined(ZARD_CONNECTOR)
330+
#define MAX_TONE_PINS DT_PROP_LEN(DT_NODELABEL(ZARD_CONNECTOR), gpio_map)
331+
#else
332+
#define MAX_TONE_PINS 1
333+
#endif
229334
#endif
230335

231336
#define TOGGLES_PER_CYCLE 2ULL

0 commit comments

Comments
 (0)