Skip to content

Commit 69afdab

Browse files
committed
zephyrCommon: Implement attachInterrupt()/detachInterrupt()
This implementation depends on CONFIG_GPIO_GET_CONFIG to keep the GPIO state already configured by pinMode(). Signed-off-by: TOKITA Hiroshi <[email protected]>
1 parent 8a28d3a commit 69afdab

File tree

1 file changed

+176
-13
lines changed

1 file changed

+176
-13
lines changed

cores/arduino/zephyrCommon.cpp

+176-13
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,158 @@
66

77
#include <Arduino.h>
88

9+
#define GPIO_MODE_MASK (GPIO_INPUT | GPIO_OUTPUT | GPIO_ACTIVE_LOW | GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN | GPIO_PULL_UP)
10+
#define LISTIFY_MAX 256
11+
12+
/*
13+
* Calculate GPIO ports/pins number statically from devicetree configuration
14+
*/
15+
16+
#define dN_gpios(N) _CONCAT(_CONCAT(d, N), _gpios)
17+
#define GPIO_ELEM(n,_) COND_CODE_1( DT_NODE_HAS_PROP(DT_PATH(zephyr_user), dN_gpios(n)), \
18+
(DEVICE_DT_GET(DT_GPIO_CTLR_BY_IDX( DT_PATH(zephyr_user), dN_gpios(n), 0)),), ())
19+
20+
#define GPIO_NGPIOS(n,_) COND_CODE_1( DT_NODE_HAS_PROP(DT_PATH(zephyr_user), dN_gpios(n)), \
21+
(DT_PROP(DT_GPIO_CTLR_BY_IDX( DT_PATH(zephyr_user), dN_gpios(n), 0), ngpios),), ())
22+
23+
namespace {
24+
25+
template<class First>
26+
constexpr int count_ngpios(const int sum, const First&) { return sum; }
27+
28+
template<class First, class Second, class... Rest>
29+
constexpr int count_ngpios(const int max, const First& first, const Second& second, const Rest&... rest)
30+
{
31+
return count_ngpios(first == second ? first.ngpios : second, second, rest...);
32+
}
33+
34+
template<class First>
35+
constexpr int count_groups(const int sum, const First&) { return sum; }
36+
37+
template<class First, class Second, class... Rest>
38+
constexpr int count_groups(const int sum, const First& first, const Second& second, const Rest&... rest)
39+
{
40+
return count_groups(first == second ? sum : sum + 1, second, rest...);
41+
}
42+
43+
template<class First>
44+
constexpr int max_in_list(const int max, const First&) { return max; }
45+
46+
template<class First, class Second, class... Rest>
47+
constexpr int max_in_list(const int max, const First& first, const Second& second, const Rest&... rest)
48+
{
49+
return max_in_list(first >= second ? first : second, second, rest...);
50+
}
51+
52+
const int port_num = count_groups(0, LISTIFY(LISTIFY_MAX, GPIO_ELEM, ()) nullptr);
53+
const int max_ngpios = max_in_list(0, LISTIFY(LISTIFY_MAX, GPIO_NGPIOS, ()) 0);
54+
55+
/*
56+
* GPIO callback implementation
57+
*/
58+
59+
struct gpio_port_callback {
60+
struct gpio_callback callback;
61+
voidFuncPtr handlers[max_ngpios];
62+
gpio_port_pins_t pins;
63+
const struct device* dev;
64+
} w_callback[port_num] = {0};
65+
66+
struct gpio_port_callback* find_gpio_port_callback(const struct device* dev)
67+
{
68+
for(size_t i=0; i<ARRAY_SIZE(w_callback); i++) {
69+
if(w_callback[i].dev == dev) {
70+
return &w_callback[i];
71+
}
72+
if(w_callback[i].dev == nullptr) {
73+
w_callback[i].dev = dev;
74+
return &w_callback[i];
75+
}
76+
}
77+
78+
return nullptr;
79+
}
80+
81+
void setInterruptHandler(pin_size_t pinNumber, voidFuncPtr func)
82+
{
83+
struct gpio_port_callback* pcb = find_gpio_port_callback(arduino_pins[pinNumber]->port);
84+
85+
if (pcb) {
86+
pcb->handlers[BIT(arduino_pins[pinNumber]->pin)] = func;
87+
}
88+
}
89+
90+
void gpioCallback(const struct device *port, struct gpio_callback *cb, uint32_t pins)
91+
{
92+
struct gpio_port_callback* pcb = (struct gpio_port_callback*)cb;
93+
94+
for(uint32_t i=0; i<max_ngpios; i++) {
95+
if (pins & BIT(i)) {
96+
pcb->handlers[BIT(i)]();
97+
}
98+
}
99+
}
100+
101+
void pinModeImpl(pin_size_t pinNumber, gpio_flags_t pinmode, voidFuncPtr callback, gpio_flags_t intmode)
102+
{
103+
gpio_pin_configure_dt(arduino_pins[pinNumber], pinmode);
104+
105+
if (callback) {
106+
struct gpio_port_callback* pcb = find_gpio_port_callback(arduino_pins[pinNumber]->port);
107+
__ASSERT(pcb != nullptr, "");
108+
109+
pcb->pins |= BIT(arduino_pins[pinNumber]->pin);
110+
setInterruptHandler(pinNumber, callback);
111+
112+
gpio_pin_interrupt_configure_dt(arduino_pins[pinNumber], intmode);
113+
gpio_init_callback(&pcb->callback, gpioCallback, pcb->pins);
114+
gpio_add_callback(arduino_pins[pinNumber]->port, &pcb->callback);
115+
}
116+
}
117+
118+
gpio_flags_t pinMode2flags(PinMode pinMode) {
119+
if (pinMode == INPUT) {
120+
return (GPIO_INPUT | GPIO_ACTIVE_HIGH);
121+
} else if (pinMode == INPUT_PULLUP) {
122+
return (GPIO_INPUT | GPIO_PULL_UP | GPIO_ACTIVE_HIGH);
123+
} else if (pinMode == INPUT_PULLDOWN) {
124+
return (GPIO_INPUT | GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH);
125+
} else if (pinMode == OUTPUT) {
126+
return (GPIO_OUTPUT_LOW | GPIO_ACTIVE_HIGH);
127+
} else {
128+
__ASSERT(false, "Not supported PinStatus");
129+
return 0;
130+
}
131+
}
132+
133+
gpio_flags_t pinStatus2flags(PinStatus status) {
134+
if (status == LOW) {
135+
return GPIO_INT_LEVEL_LOW;
136+
}
137+
else if (status == HIGH) {
138+
return GPIO_INT_LEVEL_HIGH;
139+
}
140+
else if (status == CHANGE) {
141+
return GPIO_INT_EDGE_BOTH;
142+
}
143+
else if (status == FALLING) {
144+
return GPIO_INT_EDGE_FALLING;
145+
}
146+
else if (status == RISING) {
147+
return GPIO_INT_EDGE_RISING;
148+
} else {
149+
__ASSERT(false, "Not supported OUTPUT_OPENDRAIN");
150+
return 0;
151+
}
152+
}
153+
154+
} // anonymous namespace
155+
156+
157+
/*
158+
* APIs
159+
*/
160+
9161
void yield(void) {
10162
k_yield();
11163
}
@@ -16,19 +168,14 @@ void yield(void) {
16168
* A high physical level will be interpreted as value 1
17169
*/
18170
void pinMode(pin_size_t pinNumber, PinMode pinMode) {
19-
if (pinMode == INPUT) { // input mode
20-
gpio_pin_configure_dt(arduino_pins[pinNumber],
21-
GPIO_INPUT | GPIO_ACTIVE_HIGH);
22-
} else if (pinMode == INPUT_PULLUP) { // input with internal pull-up
23-
gpio_pin_configure_dt(arduino_pins[pinNumber],
24-
GPIO_INPUT | GPIO_PULL_UP | GPIO_ACTIVE_HIGH);
25-
} else if (pinMode == INPUT_PULLDOWN) { // input with internal pull-down
26-
gpio_pin_configure_dt(arduino_pins[pinNumber],
27-
GPIO_INPUT | GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH);
28-
} else if (pinMode == OUTPUT) { // output mode
29-
gpio_pin_configure_dt(arduino_pins[pinNumber],
30-
GPIO_OUTPUT_LOW | GPIO_ACTIVE_HIGH);
31-
}
171+
gpio_flags_t pinstatus = 0;
172+
173+
#ifdef CONFIG_GPIO_GET_CONFIG
174+
/* preserve GPIO interrupt configuration */
175+
gpio_pin_get_config_dt(arduino_pins[pinNumber], &pinstatus);
176+
#endif
177+
178+
pinModeImpl(pinNumber, pinMode2flags(pinMode), nullptr, (pinstatus & ~GPIO_MODE_MASK));
32179
}
33180

34181
void digitalWrite(pin_size_t pinNumber, PinStatus status) {
@@ -39,6 +186,22 @@ PinStatus digitalRead(pin_size_t pinNumber) {
39186
return (gpio_pin_get_dt(arduino_pins[pinNumber]) == 1) ? HIGH : LOW;
40187
}
41188

189+
#ifdef CONFIG_GPIO_GET_CONFIG
190+
void attachInterrupt(pin_size_t pinNumber, voidFuncPtr callback, PinStatus pinStatus)
191+
{
192+
gpio_flags_t pinmode = 0;
193+
194+
/* preserve GPIO configuration that configured by pinMode()*/
195+
gpio_pin_get_config_dt(arduino_pins[pinNumber], &pinmode);
196+
pinModeImpl(pinNumber, (pinmode & ~GPIO_INT_MASK), callback, pinStatus2flags(pinStatus));
197+
}
198+
199+
void detachInterrupt(pin_size_t pinNumber)
200+
{
201+
setInterruptHandler(pinNumber, nullptr);
202+
}
203+
#endif
204+
42205
void delay(unsigned long ms) { k_sleep(K_MSEC(ms)); }
43206

44207
void delayMicroseconds(unsigned int us) { k_sleep(K_USEC(us)); }

0 commit comments

Comments
 (0)