Skip to content

Commit 6fa3d86

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 6fa3d86

File tree

4 files changed

+76
-10
lines changed

4 files changed

+76
-10
lines changed

cores/arduino/zephyrCommon.cpp

+25-4
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};
@@ -95,7 +100,7 @@ void setInterruptHandler(pin_size_t pinNumber, voidFuncPtr func)
95100
struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port);
96101

97102
if (pcb) {
98-
pcb->handlers[BIT(arduino_pins[pinNumber].pin)] = func;
103+
pcb->handlers[BIT(arduino_pins[pinNumber].pin)].handler = func;
99104
}
100105
}
101106

@@ -104,8 +109,8 @@ void handleGpioCallback(const struct device *port, struct gpio_callback *cb, uin
104109
struct gpio_port_callback *pcb = (struct gpio_port_callback *)cb;
105110

106111
for (uint32_t i = 0; i < max_ngpios; i++) {
107-
if (pins & BIT(i)) {
108-
pcb->handlers[BIT(i)]();
112+
if (pins & BIT(i) && pcb->handlers[BIT(i)].enabled) {
113+
pcb->handlers[BIT(i)].handler();
109114
}
110115
}
111116
}
@@ -349,3 +354,19 @@ long random(long max) {
349354
}
350355

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

cores/arduino/zephyrInternal.h

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
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+
void enableInterrupt(pin_size_t pinNumber);
12+
13+
void disableInterrupt(pin_size_t pinNumber);

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)