Skip to content

Commit 19dbd1d

Browse files
authored
Merge branch 'next' into arduino_h_cleanup
2 parents 8166fce + 73ba170 commit 19dbd1d

File tree

11 files changed

+303
-4
lines changed

11 files changed

+303
-4
lines changed

cores/arduino/zephyrCommon.cpp

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66

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

910
static const struct gpio_dt_spec arduino_pins[] = {DT_FOREACH_PROP_ELEM_SEP(
1011
DT_PATH(zephyr_user), digital_pin_gpios, GPIO_DT_SPEC_GET_BY_IDX, (, ))};
@@ -71,9 +72,14 @@ const int max_ngpios = max_in_list(
7172
* GPIO callback implementation
7273
*/
7374

75+
struct arduino_callback {
76+
voidFuncPtr handler;
77+
bool enabled;
78+
};
79+
7480
struct gpio_port_callback {
7581
struct gpio_callback callback;
76-
voidFuncPtr handlers[max_ngpios];
82+
struct arduino_callback handlers[max_ngpios];
7783
gpio_port_pins_t pins;
7884
const struct device *dev;
7985
} port_callback[port_num] = {0};
@@ -98,7 +104,7 @@ void setInterruptHandler(pin_size_t pinNumber, voidFuncPtr func)
98104
struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port);
99105

100106
if (pcb) {
101-
pcb->handlers[BIT(arduino_pins[pinNumber].pin)] = func;
107+
pcb->handlers[BIT(arduino_pins[pinNumber].pin)].handler = func;
102108
}
103109
}
104110

@@ -107,8 +113,8 @@ void handleGpioCallback(const struct device *port, struct gpio_callback *cb, uin
107113
struct gpio_port_callback *pcb = (struct gpio_port_callback *)cb;
108114

109115
for (uint32_t i = 0; i < max_ngpios; i++) {
110-
if (pins & BIT(i)) {
111-
pcb->handlers[BIT(i)]();
116+
if (pins & BIT(i) && pcb->handlers[BIT(i)].enabled) {
117+
pcb->handlers[BIT(i)].handler();
112118
}
113119
}
114120
}
@@ -324,6 +330,7 @@ void attachInterrupt(pin_size_t pinNumber, voidFuncPtr callback, PinStatus pinSt
324330

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

328335
gpio_pin_interrupt_configure(arduino_pins[pinNumber].port, arduino_pins[pinNumber].pin, intmode);
329336
gpio_init_callback(&pcb->callback, handleGpioCallback, pcb->pins);
@@ -333,6 +340,7 @@ void attachInterrupt(pin_size_t pinNumber, voidFuncPtr callback, PinStatus pinSt
333340
void detachInterrupt(pin_size_t pinNumber)
334341
{
335342
setInterruptHandler(pinNumber, nullptr);
343+
disableInterrupt(pinNumber);
336344
}
337345

338346
#ifndef CONFIG_MINIMAL_LIBC_RAND
@@ -396,3 +404,19 @@ unsigned long pulseIn(pin_size_t pinNumber, uint8_t state, unsigned long timeout
396404
}
397405

398406
#endif // CONFIG_GPIO_GET_DIRECTION
407+
408+
void enableInterrupt(pin_size_t pinNumber) {
409+
struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port);
410+
411+
if (pcb) {
412+
pcb->handlers[BIT(arduino_pins[pinNumber].pin)].enabled = true;
413+
}
414+
}
415+
416+
void disableInterrupt(pin_size_t pinNumber) {
417+
struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port);
418+
419+
if (pcb) {
420+
pcb->handlers[BIT(arduino_pins[pinNumber].pin)].enabled = false;
421+
}
422+
}

cores/arduino/zephyrInternal.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
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+
#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/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
# SPDX-License-Identifier: Apache-2.0
22

33
add_subdirectory(Wire)
4+
add_subdirectory(SPI)

libraries/SPI/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
zephyr_include_directories(.)
3+
4+
if(NOT DEFINED ARDUINO_BUILD_PATH)
5+
zephyr_sources_ifdef(CONFIG_SPI SPI.cpp)
6+
endif()

libraries/SPI/SPI.cpp

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/*
2+
* Copyright (c) 2024 Ayush Singh <ayush@beagleboard.org>
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include "SPI.h"
8+
#include "zephyrInternal.h"
9+
#include <zephyr/kernel.h>
10+
11+
/* Serial Peripheral Control Register */
12+
uint8_t SPCR;
13+
14+
arduino::ZephyrSPI::ZephyrSPI(const struct device *spi) : spi_dev(spi) {}
15+
16+
uint8_t arduino::ZephyrSPI::transfer(uint8_t data) {
17+
int ret;
18+
uint8_t rx;
19+
const struct spi_buf tx_buf = {.buf = &data, .len = sizeof(data)};
20+
const struct spi_buf_set tx_buf_set = {
21+
.buffers = &tx_buf,
22+
.count = 1,
23+
};
24+
const struct spi_buf rx_buf = {.buf = &rx, .len = sizeof(rx)};
25+
const struct spi_buf_set rx_buf_set = {
26+
.buffers = &rx_buf,
27+
.count = 1,
28+
};
29+
30+
ret = spi_transceive(spi_dev, &config, &tx_buf_set, &rx_buf_set);
31+
if (ret < 0) {
32+
return 0;
33+
}
34+
35+
return rx;
36+
}
37+
38+
uint16_t arduino::ZephyrSPI::transfer16(uint16_t data) {
39+
int ret;
40+
uint16_t rx;
41+
const struct spi_buf tx_buf = {.buf = &data, .len = sizeof(data)};
42+
const struct spi_buf_set tx_buf_set = {
43+
.buffers = &tx_buf,
44+
.count = 1,
45+
};
46+
const struct spi_buf rx_buf = {.buf = &rx, .len = sizeof(rx)};
47+
const struct spi_buf_set rx_buf_set = {
48+
.buffers = &rx_buf,
49+
.count = 1,
50+
};
51+
52+
ret = spi_transceive(spi_dev, &config, &tx_buf_set, &rx_buf_set);
53+
if (ret < 0) {
54+
return 0;
55+
}
56+
57+
return rx;
58+
}
59+
60+
void arduino::ZephyrSPI::transfer(void *buf, size_t count) {
61+
int ret;
62+
const struct spi_buf tx_buf = {.buf = buf, .len = count};
63+
const struct spi_buf_set tx_buf_set = {
64+
.buffers = &tx_buf,
65+
.count = 1,
66+
};
67+
68+
ret = spi_write(spi_dev, &config, &tx_buf_set);
69+
if (ret < 0) {
70+
return;
71+
}
72+
73+
ret = spi_read(spi_dev, &config, &tx_buf_set);
74+
if (ret < 0) {
75+
return;
76+
}
77+
}
78+
79+
void arduino::ZephyrSPI::usingInterrupt(int interruptNumber) {
80+
interrupt[interrupt_pos++] = interruptNumber;
81+
}
82+
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+
}
92+
93+
void arduino::ZephyrSPI::beginTransaction(SPISettings settings) {
94+
memset(&config, 0, sizeof(config));
95+
config.frequency = settings.getClockFreq();
96+
config.operation = ((settings.getBitOrder() ^ 1) << 4) |
97+
(settings.getDataMode() << 1) | ((SPCR >> MSTR) & 1) |
98+
SPI_WORD_SET(8);
99+
100+
detachInterrupt();
101+
}
102+
103+
void arduino::ZephyrSPI::endTransaction(void) {
104+
spi_release(spi_dev, &config);
105+
attachInterrupt();
106+
}
107+
108+
void arduino::ZephyrSPI::attachInterrupt() {
109+
for (size_t i = 0; i < interrupt_pos; ++i) {
110+
enableInterrupt(interrupt[i]);
111+
}
112+
}
113+
114+
void arduino::ZephyrSPI::detachInterrupt() {
115+
for (size_t i = 0; i < interrupt_pos; ++i) {
116+
disableInterrupt(interrupt[i]);
117+
}
118+
}
119+
120+
void arduino::ZephyrSPI::begin() {}
121+
122+
void arduino::ZephyrSPI::end() {}
123+
124+
arduino::ZephyrSPI
125+
SPI(DEVICE_DT_GET(DT_PHANDLE_BY_IDX(DT_PATH(zephyr_user), spis, 0)));

libraries/SPI/SPI.h

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
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+
#include <api/HardwareSPI.h>
11+
#include <zephyr/drivers/spi.h>
12+
13+
#define SPR0 0
14+
#define SPR1 1
15+
#define CPHA 2
16+
#define CPOL 3
17+
#define MSTR 4
18+
#define DORD 5
19+
#define SPE 6
20+
#define SPIE 7
21+
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+
28+
namespace arduino {
29+
class ZephyrSPI : public HardwareSPI {
30+
public:
31+
ZephyrSPI(const struct device *spi);
32+
33+
virtual uint8_t transfer(uint8_t data);
34+
virtual uint16_t transfer16(uint16_t data);
35+
virtual void transfer(void *buf, size_t count);
36+
37+
// Transaction Functions
38+
virtual void usingInterrupt(int interruptNumber);
39+
virtual void notUsingInterrupt(int interruptNumber);
40+
virtual void beginTransaction(SPISettings settings);
41+
virtual void endTransaction(void);
42+
43+
// SPI Configuration methods
44+
virtual void attachInterrupt();
45+
virtual void detachInterrupt();
46+
47+
virtual void begin();
48+
virtual void end();
49+
50+
private:
51+
const struct device *spi_dev;
52+
struct spi_config config;
53+
int interrupt[INTERRUPT_COUNT];
54+
size_t interrupt_pos = 0;
55+
};
56+
57+
} // namespace arduino
58+
59+
extern arduino::ZephyrSPI SPI;
60+
/* Serial Peripheral Control Register */
61+
extern uint8_t SPCR;
62+
63+
using arduino::SPI_MODE0;
64+
using arduino::SPI_MODE1;
65+
using arduino::SPI_MODE2;
66+
using arduino::SPI_MODE3;
67+
using arduino::SPISettings;

samples/spi_controller/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
cmake_minimum_required(VERSION 3.20.0)
4+
5+
cmake_path(SET ZephyrBase $ENV{ZEPHYR_BASE})
6+
set(DTC_OVERLAY_FILE ${ZephyrBase}/../modules/lib/Arduino-Zephyr-API/variants/${BOARD}/${BOARD}.overlay)
7+
8+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
9+
project(spi_controller)
10+
11+
target_sources(app PRIVATE src/app.cpp)
12+
13+
zephyr_compile_options(-Wno-unused-variable -Wno-comment)

samples/spi_controller/README.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.. _spi_controller:
2+
3+
SPI Controller
4+
###############
5+
6+
Overview
7+
********
8+
9+
A simple sample that sends incrementing byte to SPI peripheral.

samples/spi_controller/prj.conf

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
CONFIG_CPLUSPLUS=y
2+
CONFIG_ARDUINO_API=y
3+
CONFIG_SPI=y
4+
CONFIG_LOG=y
5+
CONFIG_LOG_OUTPUT=y
6+
CONFIG_LOG_MODE_IMMEDIATE=y

samples/spi_controller/src/app.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright (c) 2024 Ayush Singh <ayush@beagleboard.org>
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include "SPI.h"
8+
#include <Arduino.h>
9+
10+
#define CHIPSELECT 3
11+
12+
static uint8_t data = 0;
13+
14+
void setup() {
15+
SPI.begin();
16+
pinMode(CHIPSELECT, OUTPUT);
17+
digitalWrite(CHIPSELECT, HIGH);
18+
}
19+
20+
void loop() {
21+
SPI.beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE0));
22+
digitalWrite(CHIPSELECT, LOW);
23+
SPI.transfer(data++);
24+
digitalWrite(CHIPSELECT, HIGH);
25+
SPI.endTransaction();
26+
delay(1000);
27+
}

variants/beagleconnect_freedom/beagleconnect_freedom.overlay

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
builtin-led-gpios = <&gpio0 18 GPIO_ACTIVE_HIGH>; /* 2.4GHz TX/RX */
5151
serials = <&uart0 &uart1>;
5252
i2cs = <&i2c0>;
53+
spis = <&spi0>;
5354
};
5455
};
5556

0 commit comments

Comments
 (0)