Skip to content

Commit f680b98

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 <ayush@beagleboard.org>
1 parent a9f58ba commit f680b98

File tree

4 files changed

+78
-10
lines changed

4 files changed

+78
-10
lines changed

cores/arduino/zephyrCommon.cpp

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,14 @@ const int max_ngpios = max_in_list(
6868
* GPIO callback implementation
6969
*/
7070

71+
struct arduino_callback {
72+
voidFuncPtr handler;
73+
bool enabled;
74+
};
75+
7176
struct gpio_port_callback {
7277
struct gpio_callback callback;
73-
voidFuncPtr handlers[max_ngpios];
78+
struct arduino_callback handlers[max_ngpios];
7479
gpio_port_pins_t pins;
7580
const struct device *dev;
7681
} port_callback[port_num] = {0};
@@ -90,12 +95,28 @@ struct gpio_port_callback *find_gpio_port_callback(const struct device *dev)
9095
return nullptr;
9196
}
9297

98+
void enableInterrupt(pin_size_t pinNumber) {
99+
struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port);
100+
101+
if (pcb) {
102+
pcb->handlers[BIT(arduino_pins[pinNumber].pin)].enabled = true;
103+
}
104+
}
105+
106+
void disableInterrupt(pin_size_t pinNumber) {
107+
struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port);
108+
109+
if (pcb) {
110+
pcb->handlers[BIT(arduino_pins[pinNumber].pin)].enabled = false;
111+
}
112+
}
113+
93114
void setInterruptHandler(pin_size_t pinNumber, voidFuncPtr func)
94115
{
95116
struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port);
96117

97118
if (pcb) {
98-
pcb->handlers[BIT(arduino_pins[pinNumber].pin)] = func;
119+
pcb->handlers[BIT(arduino_pins[pinNumber].pin)].handler = func;
99120
}
100121
}
101122

@@ -104,8 +125,8 @@ void handleGpioCallback(const struct device *port, struct gpio_callback *cb, uin
104125
struct gpio_port_callback *pcb = (struct gpio_port_callback *)cb;
105126

106127
for (uint32_t i = 0; i < max_ngpios; i++) {
107-
if (pins & BIT(i)) {
108-
pcb->handlers[BIT(i)]();
128+
if (pins & BIT(i) && pcb->handlers[BIT(i)].enabled) {
129+
pcb->handlers[BIT(i)].handler();
109130
}
110131
}
111132
}
@@ -321,6 +342,7 @@ void attachInterrupt(pin_size_t pinNumber, voidFuncPtr callback, PinStatus pinSt
321342

322343
pcb->pins |= BIT(arduino_pins[pinNumber].pin);
323344
setInterruptHandler(pinNumber, callback);
345+
enableInterrupt(pinNumber);
324346

325347
gpio_pin_interrupt_configure(arduino_pins[pinNumber].port, arduino_pins[pinNumber].pin, intmode);
326348
gpio_init_callback(&pcb->callback, handleGpioCallback, pcb->pins);
@@ -330,6 +352,7 @@ void attachInterrupt(pin_size_t pinNumber, voidFuncPtr callback, PinStatus pinSt
330352
void detachInterrupt(pin_size_t pinNumber)
331353
{
332354
setInterruptHandler(pinNumber, nullptr);
355+
disableInterrupt(pinNumber);
333356
}
334357

335358
#ifndef CONFIG_MINIMAL_LIBC_RAND

cores/arduino/zephyrInternal.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/*
2+
* Copyright (c) 2024 Ayush Singh <ayush@beagleboard.org>
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#pragma once
8+
9+
#include <Arduino.h>
10+
11+
void enableInterrupt(pin_size_t pinNumber);
12+
13+
void disableInterrupt(pin_size_t pinNumber);

libraries/SPI/SPI.cpp

Lines changed: 29 additions & 5 deletions
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

Lines changed: 9 additions & 1 deletion
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)