Skip to content

Commit 459001c

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 5a76d45 commit 459001c

File tree

1 file changed

+172
-13
lines changed

1 file changed

+172
-13
lines changed

cores/arduino/zephyrCommon.cpp

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

34176
void digitalWrite(pin_size_t pinNumber, PinStatus status) {
@@ -49,3 +191,20 @@ unsigned long micros(void) {
49191

50192
unsigned long millis(void) { return k_uptime_get_32(); }
51193

194+
#ifdef CONFIG_GPIO_GET_CONFIG
195+
196+
void attachInterrupt(pin_size_t pinNumber, voidFuncPtr callback, PinStatus pinStatus)
197+
{
198+
gpio_flags_t pinmode = 0;
199+
200+
/* preserve GPIO configuration that configured by pinMode()*/
201+
gpio_pin_get_config_dt(arduino_pins[pinNumber], &pinmode);
202+
pinModeImpl(pinNumber, (pinmode & ~GPIO_INT_MASK), callback, pinStatus2flags(pinStatus));
203+
}
204+
205+
void detachInterrupt(pin_size_t pinNumber)
206+
{
207+
setInterruptHandler(pinNumber, nullptr);
208+
}
209+
210+
#endif

0 commit comments

Comments
 (0)