Skip to content

Commit

Permalink
Interrupt support
Browse files Browse the repository at this point in the history
- 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>
  • Loading branch information
Ayush1325 committed Jun 14, 2024
1 parent a9f58ba commit 7b3c1fe
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 10 deletions.
32 changes: 28 additions & 4 deletions cores/arduino/zephyrCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/

#include <Arduino.h>
#include "zephyrInternal.h"

namespace {

Expand Down Expand Up @@ -68,9 +69,14 @@ const int max_ngpios = max_in_list(
* GPIO callback implementation
*/

struct arduino_callback {
voidFuncPtr handler;
bool enabled;
};

struct gpio_port_callback {
struct gpio_callback callback;
voidFuncPtr handlers[max_ngpios];
struct arduino_callback handlers[max_ngpios];
gpio_port_pins_t pins;
const struct device *dev;
} port_callback[port_num] = {0};
Expand All @@ -95,7 +101,7 @@ void setInterruptHandler(pin_size_t pinNumber, voidFuncPtr func)
struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port);

if (pcb) {
pcb->handlers[BIT(arduino_pins[pinNumber].pin)] = func;
pcb->handlers[BIT(arduino_pins[pinNumber].pin)].handler = func;
}
}

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

for (uint32_t i = 0; i < max_ngpios; i++) {
if (pins & BIT(i)) {
pcb->handlers[BIT(i)]();
if (pins & BIT(i) && pcb->handlers[BIT(i)].enabled) {
pcb->handlers[BIT(i)].handler();
}
}
}
Expand Down Expand Up @@ -321,6 +327,7 @@ void attachInterrupt(pin_size_t pinNumber, voidFuncPtr callback, PinStatus pinSt

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

gpio_pin_interrupt_configure(arduino_pins[pinNumber].port, arduino_pins[pinNumber].pin, intmode);
gpio_init_callback(&pcb->callback, handleGpioCallback, pcb->pins);
Expand All @@ -330,6 +337,7 @@ void attachInterrupt(pin_size_t pinNumber, voidFuncPtr callback, PinStatus pinSt
void detachInterrupt(pin_size_t pinNumber)
{
setInterruptHandler(pinNumber, nullptr);
disableInterrupt(pinNumber);
}

#ifndef CONFIG_MINIMAL_LIBC_RAND
Expand All @@ -349,3 +357,19 @@ long random(long max) {
}

#endif

void enableInterrupt(pin_size_t pinNumber) {
struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port);

if (pcb) {
pcb->handlers[BIT(arduino_pins[pinNumber].pin)].enabled = true;
}
}

void disableInterrupt(pin_size_t pinNumber) {
struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port);

if (pcb) {
pcb->handlers[BIT(arduino_pins[pinNumber].pin)].enabled = false;
}
}
20 changes: 20 additions & 0 deletions cores/arduino/zephyrInternal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright (c) 2024 Ayush Singh <ayush@beagleboard.org>
*
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once

#include <Arduino.h>

#ifdef __cplusplus
extern "C" {
#endif

void enableInterrupt(pin_size_t);
void disableInterrupt(pin_size_t);

#ifdef __cplusplus
} // extern "C"
#endif
34 changes: 29 additions & 5 deletions libraries/SPI/SPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/

#include "SPI.h"
#include "zephyrInternal.h"
#include <zephyr/kernel.h>

/* Serial Peripheral Control Register */
Expand Down Expand Up @@ -75,23 +76,46 @@ void arduino::ZephyrSPI::transfer(void *buf, size_t count) {
}
}

void arduino::ZephyrSPI::usingInterrupt(int interruptNumber) {}
void arduino::ZephyrSPI::usingInterrupt(int interruptNumber) {
interrupt[interrupt_pos++] = interruptNumber;
}

void arduino::ZephyrSPI::notUsingInterrupt(int interruptNumber) {}
void arduino::ZephyrSPI::notUsingInterrupt(int interruptNumber) {
for (size_t i = 0; i < interrupt_pos; ++i) {
if (interrupt[i] == interruptNumber) {
memmove(&interrupt[i], &interrupt[i + 1], interrupt_pos - i - 1);
interrupt_pos--;
break;
}
}
}

void arduino::ZephyrSPI::beginTransaction(SPISettings settings) {
memset(&config, 0, sizeof(config));
config.frequency = settings.getClockFreq();
config.operation = ((settings.getBitOrder() ^ 1) << 4) |
(settings.getDataMode() << 1) | ((SPCR >> MSTR) & 1) |
SPI_WORD_SET(8);

detachInterrupt();
}

void arduino::ZephyrSPI::endTransaction(void) { spi_release(spi_dev, &config); }
void arduino::ZephyrSPI::endTransaction(void) {
spi_release(spi_dev, &config);
attachInterrupt();
}

void arduino::ZephyrSPI::attachInterrupt() {}
void arduino::ZephyrSPI::attachInterrupt() {
for (size_t i = 0; i < interrupt_pos; ++i) {
enableInterrupt(interrupt[i]);
}
}

void arduino::ZephyrSPI::detachInterrupt() {}
void arduino::ZephyrSPI::detachInterrupt() {
for (size_t i = 0; i < interrupt_pos; ++i) {
disableInterrupt(interrupt[i]);
}
}

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

Expand Down
10 changes: 9 additions & 1 deletion libraries/SPI/SPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@
#define SPE 6
#define SPIE 7

/* Count the number of GPIOs for limit of number of interrupts */
#define INTERRUPT_HELPER(n, p, i) 1
#define INTERRUPT_COUNT \
DT_FOREACH_PROP_ELEM_SEP(DT_PATH(zephyr_user), digital_pin_gpios, \
INTERRUPT_HELPER, (+))

namespace arduino {
class ZephyrSPI : public HardwareSPI {
public:
Expand All @@ -43,7 +49,9 @@ class ZephyrSPI : public HardwareSPI {

private:
const struct device *spi_dev;
struct spi_config config;
struct spi_config config;
int interrupt[INTERRUPT_COUNT];
size_t interrupt_pos = 0;
};

} // namespace arduino
Expand Down

0 comments on commit 7b3c1fe

Please sign in to comment.