From 91390aca585a28c475b8dc1070501ee34375c3ec Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Wed, 10 Dec 2025 15:05:27 +0100 Subject: [PATCH 1/2] fix: SPI: remove holes between transfer() Fixes #145 --- libraries/SPI/SPI.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/SPI/SPI.cpp b/libraries/SPI/SPI.cpp index 1a0b3911..33ddd319 100644 --- a/libraries/SPI/SPI.cpp +++ b/libraries/SPI/SPI.cpp @@ -57,7 +57,7 @@ void arduino::ZephyrSPI::notUsingInterrupt(int interruptNumber) { } void arduino::ZephyrSPI::beginTransaction(SPISettings settings) { - uint32_t mode = 0; + uint32_t mode = SPI_HOLD_ON_CS; // Set bus mode switch (settings.getBusMode()) { From 95b2b95922811abdf099e5f3492936ef2039e0b0 Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Thu, 18 Dec 2025 11:12:43 +0100 Subject: [PATCH 2/2] SPI: fix: avoid locks with 8/16 bit transfers When SPI_HOLD_ON_CS is set, Zephyr holds CS down until the 'spi_release' API is called, which is the behavior expected by Arduino users. However, this requires SPI_LOCK_ON to also be set, and that uses the pointer to 'spi_config' structure to identify the lock holder. Using two different structures for 8-bit and 16-bit transfers causes the lock to not work as intended, causing the sketch to hang. Rework code to only use a single 'spi_config' structure and update the 'operation' field as needed. Signed-off-by: Luca Burelli --- libraries/SPI/SPI.cpp | 23 ++++++++--------------- libraries/SPI/SPI.h | 4 ++-- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/libraries/SPI/SPI.cpp b/libraries/SPI/SPI.cpp index 33ddd319..8a15fc71 100644 --- a/libraries/SPI/SPI.cpp +++ b/libraries/SPI/SPI.cpp @@ -13,7 +13,7 @@ arduino::ZephyrSPI::ZephyrSPI(const struct device *spi) : spi_dev(spi) { uint8_t arduino::ZephyrSPI::transfer(uint8_t data) { uint8_t rx = data; - if (transfer(&rx, sizeof(rx), &config) < 0) { + if (transfer(&rx, sizeof(rx), SPI_WORD_SET(8)) < 0) { return 0; } return rx; @@ -21,20 +21,18 @@ uint8_t arduino::ZephyrSPI::transfer(uint8_t data) { uint16_t arduino::ZephyrSPI::transfer16(uint16_t data) { uint16_t rx = data; - if (transfer(&rx, sizeof(rx), &config16) < 0) { + if (transfer(&rx, sizeof(rx), SPI_WORD_SET(16)) < 0) { return 0; } return rx; } void arduino::ZephyrSPI::transfer(void *buf, size_t count) { - int ret = transfer(buf, count, &config); + int ret = transfer(buf, count, SPI_WORD_SET(8)); (void)ret; } -int arduino::ZephyrSPI::transfer(void *buf, size_t len, const struct spi_config *config) { - int ret; - +int arduino::ZephyrSPI::transfer(void *buf, size_t len, uint32_t flags) { const struct spi_buf tx_buf = {.buf = buf, .len = len}; const struct spi_buf_set tx_buf_set = { .buffers = &tx_buf, @@ -47,7 +45,8 @@ int arduino::ZephyrSPI::transfer(void *buf, size_t len, const struct spi_config .count = 1, }; - return spi_transceive(spi_dev, config, &tx_buf_set, &rx_buf_set); + config.operation = mode | flags; + return spi_transceive(spi_dev, &config, &tx_buf_set, &rx_buf_set); } void arduino::ZephyrSPI::usingInterrupt(int interruptNumber) { @@ -57,7 +56,7 @@ void arduino::ZephyrSPI::notUsingInterrupt(int interruptNumber) { } void arduino::ZephyrSPI::beginTransaction(SPISettings settings) { - uint32_t mode = SPI_HOLD_ON_CS; + mode = SPI_HOLD_ON_CS; // Set bus mode switch (settings.getBusMode()) { @@ -93,15 +92,9 @@ void arduino::ZephyrSPI::beginTransaction(SPISettings settings) { break; } - // Set SPI configuration structure for 8-bit transfers + // Set SPI configuration structure except for operation memset(&config, 0, sizeof(struct spi_config)); - config.operation = mode | SPI_WORD_SET(8); config.frequency = max(SPI_MIN_CLOCK_FREQUENCY, settings.getClockFreq()); - - // Set SPI configuration structure for 16-bit transfers - memset(&config16, 0, sizeof(struct spi_config)); - config16.operation = mode | SPI_WORD_SET(16); - config16.frequency = max(SPI_MIN_CLOCK_FREQUENCY, settings.getClockFreq()); } void arduino::ZephyrSPI::endTransaction(void) { diff --git a/libraries/SPI/SPI.h b/libraries/SPI/SPI.h index 2a25a8bf..aea31697 100644 --- a/libraries/SPI/SPI.h +++ b/libraries/SPI/SPI.h @@ -59,12 +59,12 @@ class ZephyrSPI : public HardwareSPI { virtual void end(); private: - int transfer(void *buf, size_t len, const struct spi_config *config); + int transfer(void *buf, size_t len, uint32_t flags); protected: const struct device *spi_dev; struct spi_config config; - struct spi_config config16; + uint32_t mode; int interrupt[INTERRUPT_COUNT]; size_t interrupt_pos = 0; };