Skip to content

Commit 7b3c1fe

Browse files
committed
Interrupt support
- Disable registered interrupts on beginTransaction and re-enable on endTransaction. - Add zephyrInternal.h for APIs not meant for external consumption Signed-off-by: Ayush Singh <[email protected]>
1 parent a9f58ba commit 7b3c1fe

File tree

4 files changed

+86
-10
lines changed

4 files changed

+86
-10
lines changed

cores/arduino/zephyrCommon.cpp

+28-4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66

77
#include <Arduino.h>
8+
#include "zephyrInternal.h"
89

910
namespace {
1011

@@ -68,9 +69,14 @@ const int max_ngpios = max_in_list(
6869
* GPIO callback implementation
6970
*/
7071

72+
struct arduino_callback {
73+
voidFuncPtr handler;
74+
bool enabled;
75+
};
76+
7177
struct gpio_port_callback {
7278
struct gpio_callback callback;
73-
voidFuncPtr handlers[max_ngpios];
79+
struct arduino_callback handlers[max_ngpios];
7480
gpio_port_pins_t pins;
7581
const struct device *dev;
7682
} port_callback[port_num] = {0};
@@ -95,7 +101,7 @@ void setInterruptHandler(pin_size_t pinNumber, voidFuncPtr func)
95101
struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port);
96102

97103
if (pcb) {
98-
pcb->handlers[BIT(arduino_pins[pinNumber].pin)] = func;
104+
pcb->handlers[BIT(arduino_pins[pinNumber].pin)].handler = func;
99105
}
100106
}
101107

@@ -104,8 +110,8 @@ void handleGpioCallback(const struct device *port, struct gpio_callback *cb, uin
104110
struct gpio_port_callback *pcb = (struct gpio_port_callback *)cb;
105111

106112
for (uint32_t i = 0; i < max_ngpios; i++) {
107-
if (pins & BIT(i)) {
108-
pcb->handlers[BIT(i)]();
113+
if (pins & BIT(i) && pcb->handlers[BIT(i)].enabled) {
114+
pcb->handlers[BIT(i)].handler();
109115
}
110116
}
111117
}
@@ -321,6 +327,7 @@ void attachInterrupt(pin_size_t pinNumber, voidFuncPtr callback, PinStatus pinSt
321327

322328
pcb->pins |= BIT(arduino_pins[pinNumber].pin);
323329
setInterruptHandler(pinNumber, callback);
330+
enableInterrupt(pinNumber);
324331

325332
gpio_pin_interrupt_configure(arduino_pins[pinNumber].port, arduino_pins[pinNumber].pin, intmode);
326333
gpio_init_callback(&pcb->callback, handleGpioCallback, pcb->pins);
@@ -330,6 +337,7 @@ void attachInterrupt(pin_size_t pinNumber, voidFuncPtr callback, PinStatus pinSt
330337
void detachInterrupt(pin_size_t pinNumber)
331338
{
332339
setInterruptHandler(pinNumber, nullptr);
340+
disableInterrupt(pinNumber);
333341
}
334342

335343
#ifndef CONFIG_MINIMAL_LIBC_RAND
@@ -349,3 +357,19 @@ long random(long max) {
349357
}
350358

351359
#endif
360+
361+
void enableInterrupt(pin_size_t pinNumber) {
362+
struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port);
363+
364+
if (pcb) {
365+
pcb->handlers[BIT(arduino_pins[pinNumber].pin)].enabled = true;
366+
}
367+
}
368+
369+
void disableInterrupt(pin_size_t pinNumber) {
370+
struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port);
371+
372+
if (pcb) {
373+
pcb->handlers[BIT(arduino_pins[pinNumber].pin)].enabled = false;
374+
}
375+
}

cores/arduino/zephyrInternal.h

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Copyright (c) 2024 Ayush Singh <[email protected]>
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#pragma once
8+
9+
#include <Arduino.h>
10+
11+
#ifdef __cplusplus
12+
extern "C" {
13+
#endif
14+
15+
void enableInterrupt(pin_size_t);
16+
void disableInterrupt(pin_size_t);
17+
18+
#ifdef __cplusplus
19+
} // extern "C"
20+
#endif

libraries/SPI/SPI.cpp

+29-5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66

77
#include "SPI.h"
8+
#include "zephyrInternal.h"
89
#include <zephyr/kernel.h>
910

1011
/* Serial Peripheral Control Register */
@@ -75,23 +76,46 @@ void arduino::ZephyrSPI::transfer(void *buf, size_t count) {
7576
}
7677
}
7778

78-
void arduino::ZephyrSPI::usingInterrupt(int interruptNumber) {}
79+
void arduino::ZephyrSPI::usingInterrupt(int interruptNumber) {
80+
interrupt[interrupt_pos++] = interruptNumber;
81+
}
7982

80-
void arduino::ZephyrSPI::notUsingInterrupt(int interruptNumber) {}
83+
void arduino::ZephyrSPI::notUsingInterrupt(int interruptNumber) {
84+
for (size_t i = 0; i < interrupt_pos; ++i) {
85+
if (interrupt[i] == interruptNumber) {
86+
memmove(&interrupt[i], &interrupt[i + 1], interrupt_pos - i - 1);
87+
interrupt_pos--;
88+
break;
89+
}
90+
}
91+
}
8192

8293
void arduino::ZephyrSPI::beginTransaction(SPISettings settings) {
8394
memset(&config, 0, sizeof(config));
8495
config.frequency = settings.getClockFreq();
8596
config.operation = ((settings.getBitOrder() ^ 1) << 4) |
8697
(settings.getDataMode() << 1) | ((SPCR >> MSTR) & 1) |
8798
SPI_WORD_SET(8);
99+
100+
detachInterrupt();
88101
}
89102

90-
void arduino::ZephyrSPI::endTransaction(void) { spi_release(spi_dev, &config); }
103+
void arduino::ZephyrSPI::endTransaction(void) {
104+
spi_release(spi_dev, &config);
105+
attachInterrupt();
106+
}
91107

92-
void arduino::ZephyrSPI::attachInterrupt() {}
108+
void arduino::ZephyrSPI::attachInterrupt() {
109+
for (size_t i = 0; i < interrupt_pos; ++i) {
110+
enableInterrupt(interrupt[i]);
111+
}
112+
}
93113

94-
void arduino::ZephyrSPI::detachInterrupt() {}
114+
void arduino::ZephyrSPI::detachInterrupt() {
115+
for (size_t i = 0; i < interrupt_pos; ++i) {
116+
disableInterrupt(interrupt[i]);
117+
}
118+
}
95119

96120
void arduino::ZephyrSPI::begin() {}
97121

libraries/SPI/SPI.h

+9-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@
1919
#define SPE 6
2020
#define SPIE 7
2121

22+
/* Count the number of GPIOs for limit of number of interrupts */
23+
#define INTERRUPT_HELPER(n, p, i) 1
24+
#define INTERRUPT_COUNT \
25+
DT_FOREACH_PROP_ELEM_SEP(DT_PATH(zephyr_user), digital_pin_gpios, \
26+
INTERRUPT_HELPER, (+))
27+
2228
namespace arduino {
2329
class ZephyrSPI : public HardwareSPI {
2430
public:
@@ -43,7 +49,9 @@ class ZephyrSPI : public HardwareSPI {
4349

4450
private:
4551
const struct device *spi_dev;
46-
struct spi_config config;
52+
struct spi_config config;
53+
int interrupt[INTERRUPT_COUNT];
54+
size_t interrupt_pos = 0;
4755
};
4856

4957
} // namespace arduino

0 commit comments

Comments
 (0)