From dc79a2a523b77b053a0e332053889eccd65e2d47 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Tue, 1 Oct 2024 11:08:18 +0200 Subject: [PATCH 01/15] SPI: fix library compliance --- libraries/SPI/SPI.cpp | 58 +++++++++++++++++-------------------------- libraries/SPI/SPI.h | 4 ++- 2 files changed, 26 insertions(+), 36 deletions(-) diff --git a/libraries/SPI/SPI.cpp b/libraries/SPI/SPI.cpp index d47d84cc2..cfea9af7c 100644 --- a/libraries/SPI/SPI.cpp +++ b/libraries/SPI/SPI.cpp @@ -8,9 +8,6 @@ #include "zephyrInternal.h" #include -/* Serial Peripheral Control Register */ -uint8_t SPCR; - arduino::ZephyrSPI::ZephyrSPI(const struct device *spi) : spi_dev(spi) {} uint8_t arduino::ZephyrSPI::transfer(uint8_t data) { @@ -65,57 +62,48 @@ void arduino::ZephyrSPI::transfer(void *buf, size_t count) { .count = 1, }; - ret = spi_write(spi_dev, &config, &tx_buf_set); - if (ret < 0) { - return; - } + uint8_t rx[count]; + const struct spi_buf rx_buf = {.buf = &rx, .len = count}; + const struct spi_buf_set rx_buf_set = { + .buffers = &rx_buf, + .count = 1, + }; - ret = spi_read(spi_dev, &config, &tx_buf_set); - if (ret < 0) { - return; - } + spi_transceive(spi_dev, &config, &tx_buf_set, &rx_buf_set); + memcpy(buf, rx, count); } void arduino::ZephyrSPI::usingInterrupt(int interruptNumber) { - interrupt[interrupt_pos++] = 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(); + auto mode = SPI_MODE_CPOL | SPI_MODE_CPHA; + switch (settings.getDataMode()) { + case SPI_MODE0: + mode = 0; break; + case SPI_MODE1: + mode = SPI_MODE_CPHA; break; + case SPI_MODE2: + mode = SPI_MODE_CPOL; break; + case SPI_MODE3: + mode = SPI_MODE_CPOL | SPI_MODE_CPHA; break; + } + config.operation = SPI_WORD_SET(8) | (settings.getBitOrder() == MSBFIRST ? SPI_TRANSFER_MSB : SPI_TRANSFER_LSB) | mode; } void arduino::ZephyrSPI::endTransaction(void) { spi_release(spi_dev, &config); - attachInterrupt(); } -void arduino::ZephyrSPI::attachInterrupt() { - for (size_t i = 0; i < interrupt_pos; ++i) { - enableInterrupt(interrupt[i]); - } -} +void arduino::ZephyrSPI::attachInterrupt() {} + +void arduino::ZephyrSPI::detachInterrupt() {} -void arduino::ZephyrSPI::detachInterrupt() { - for (size_t i = 0; i < interrupt_pos; ++i) { - disableInterrupt(interrupt[i]); - } -} void arduino::ZephyrSPI::begin() {} diff --git a/libraries/SPI/SPI.h b/libraries/SPI/SPI.h index 5d448d7a2..7d53351fc 100644 --- a/libraries/SPI/SPI.h +++ b/libraries/SPI/SPI.h @@ -10,6 +10,9 @@ #include #include +#undef SPI +#undef SPI1 + #define SPR0 0 #define SPR1 1 #define CPHA 2 @@ -75,7 +78,6 @@ extern arduino::ZephyrSPI SPI; #endif /* Serial Peripheral Control Register */ -extern uint8_t SPCR; using arduino::SPI_MODE0; using arduino::SPI_MODE1; From 5366a59f1d1756856884ed3634da62e5a9484486 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Tue, 1 Oct 2024 11:08:37 +0200 Subject: [PATCH 02/15] Wire: remove debug --- libraries/Wire/Wire.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/libraries/Wire/Wire.cpp b/libraries/Wire/Wire.cpp index 7fc64b030..f1df222f7 100644 --- a/libraries/Wire/Wire.cpp +++ b/libraries/Wire/Wire.cpp @@ -45,13 +45,11 @@ size_t arduino::ZephyrI2C::requestFrom(uint8_t address, size_t len, int ret = i2c_read(i2c_dev, rxRingBuffer.buffer, len, address); if (ret != 0) { - printk("\n\nERR: i2c burst read fails\n\n\n"); return 0; } ret = ring_buf_put(&rxRingBuffer.rb, rxRingBuffer.buffer, len); if (ret == 0) { - printk("\n\nERR: buff put fails\n\n\n"); return 0; } return len; @@ -80,7 +78,6 @@ int arduino::ZephyrI2C::read() { if (ring_buf_peek(&rxRingBuffer.rb, buf, 1) > 0) { int ret = ring_buf_get(&rxRingBuffer.rb, buf, 1); if (ret == 0) { - printk("\n\nERR: buff empty\n\n\n"); return 0; } return (int)buf[0]; @@ -89,7 +86,7 @@ int arduino::ZephyrI2C::read() { } int arduino::ZephyrI2C::available() { // TODO for ADS1115 - return !ring_buf_is_empty(&rxRingBuffer.rb); // ret 0 if empty + return ring_buf_size_get(&rxRingBuffer.rb); // ret 0 if empty } int arduino::ZephyrI2C::peek() { @@ -121,7 +118,7 @@ DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), i2cs, DECLARE_WIRE_N) #undef DECL_WIRE_N #undef DECL_WIRE_0 #undef ARDUINO_WIRE_DEFINED_0 -#else // PROP_LEN(i2cs) > 1 +#elif (DT_PROP_LEN(DT_PATH(zephyr_user), i2cs) == 1) /* When PROP_LEN(i2cs) == 1, DT_FOREACH_PROP_ELEM work not correctly. */ arduino::ZephyrI2C Wire(DEVICE_DT_GET(DT_PHANDLE_BY_IDX(DT_PATH(zephyr_user), i2cs, 0))); #endif // HAS_PORP(i2cs) From ff00459d1e002dca8325505931493ed456cf5b71 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Mon, 9 Dec 2024 16:18:38 +0100 Subject: [PATCH 03/15] SPI: provide a hook to set the minimum SPI frequency On Giga, the system will complain loudly if the frequency selected is too low ``` spi_ll_stm32: Unsupported frequency 400000Hz, max 120000000Hz, min 937500Hz``` Let's try to keep this at minimum or change when we'll be able to grab the same infor from a macro/API provided by zephyr --- libraries/SPI/SPI.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libraries/SPI/SPI.cpp b/libraries/SPI/SPI.cpp index cfea9af7c..f55c17c26 100644 --- a/libraries/SPI/SPI.cpp +++ b/libraries/SPI/SPI.cpp @@ -79,9 +79,13 @@ void arduino::ZephyrSPI::usingInterrupt(int interruptNumber) { void arduino::ZephyrSPI::notUsingInterrupt(int interruptNumber) { } +#ifndef SPI_MIN_CLOCK_FEQUENCY +#define SPI_MIN_CLOCK_FEQUENCY 1000000 +#endif + void arduino::ZephyrSPI::beginTransaction(SPISettings settings) { memset(&config, 0, sizeof(config)); - config.frequency = settings.getClockFreq(); + config.frequency = settings.getClockFreq() > SPI_MIN_CLOCK_FEQUENCY ? settings.getClockFreq() : SPI_MIN_CLOCK_FEQUENCY; auto mode = SPI_MODE_CPOL | SPI_MODE_CPHA; switch (settings.getDataMode()) { case SPI_MODE0: From 525eb53a6354669cf1bc7416b98cbe28fcdf996e Mon Sep 17 00:00:00 2001 From: kurte Date: Wed, 18 Dec 2024 07:42:38 -0800 Subject: [PATCH 04/15] SPI - Fix Transfer16 plus allow subclass to gain access to member variables resolves #13 And: provides for c) option in #14 In particular, added another config option (config16) that is initialized at beginTransaction with same settings as config except word size set to 16 instead of 8. Also: updated begin() to call beginTransaction with default SPISettings, and the endTransaction, such that sketches that don't call beginTransaction output at the default settings. Changed the header file private: to protected --- libraries/SPI/SPI.cpp | 11 +++++++++-- libraries/SPI/SPI.h | 3 ++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/libraries/SPI/SPI.cpp b/libraries/SPI/SPI.cpp index f55c17c26..897d57f2a 100644 --- a/libraries/SPI/SPI.cpp +++ b/libraries/SPI/SPI.cpp @@ -46,7 +46,7 @@ uint16_t arduino::ZephyrSPI::transfer16(uint16_t data) { .count = 1, }; - ret = spi_transceive(spi_dev, &config, &tx_buf_set, &rx_buf_set); + ret = spi_transceive(spi_dev, &config16, &tx_buf_set, &rx_buf_set); if (ret < 0) { return 0; } @@ -85,7 +85,10 @@ void arduino::ZephyrSPI::notUsingInterrupt(int interruptNumber) { void arduino::ZephyrSPI::beginTransaction(SPISettings settings) { memset(&config, 0, sizeof(config)); + memset(&config16, 0, sizeof(config16)); config.frequency = settings.getClockFreq() > SPI_MIN_CLOCK_FEQUENCY ? settings.getClockFreq() : SPI_MIN_CLOCK_FEQUENCY; + config16.frequency = config.frequency; + auto mode = SPI_MODE_CPOL | SPI_MODE_CPHA; switch (settings.getDataMode()) { case SPI_MODE0: @@ -98,6 +101,7 @@ void arduino::ZephyrSPI::beginTransaction(SPISettings settings) { mode = SPI_MODE_CPOL | SPI_MODE_CPHA; break; } config.operation = SPI_WORD_SET(8) | (settings.getBitOrder() == MSBFIRST ? SPI_TRANSFER_MSB : SPI_TRANSFER_LSB) | mode; + config16.operation = SPI_WORD_SET(16) | (settings.getBitOrder() == MSBFIRST ? SPI_TRANSFER_MSB : SPI_TRANSFER_LSB) | mode; } void arduino::ZephyrSPI::endTransaction(void) { @@ -109,7 +113,10 @@ void arduino::ZephyrSPI::attachInterrupt() {} void arduino::ZephyrSPI::detachInterrupt() {} -void arduino::ZephyrSPI::begin() {} +void arduino::ZephyrSPI::begin() { + beginTransaction(SPISettings()); + endTransaction(); +} void arduino::ZephyrSPI::end() {} diff --git a/libraries/SPI/SPI.h b/libraries/SPI/SPI.h index 7d53351fc..ec3b68695 100644 --- a/libraries/SPI/SPI.h +++ b/libraries/SPI/SPI.h @@ -50,9 +50,10 @@ class ZephyrSPI : public HardwareSPI { virtual void begin(); virtual void end(); -private: +protected: const struct device *spi_dev; struct spi_config config; + struct spi_config config16; int interrupt[INTERRUPT_COUNT]; size_t interrupt_pos = 0; }; From 32099ac3e320d607f93385959bc473171b6e4208 Mon Sep 17 00:00:00 2001 From: Mike S Date: Wed, 8 Jan 2025 13:35:46 -0500 Subject: [PATCH 05/15] Implement SetClock Function --- libraries/Wire/Wire.cpp | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/libraries/Wire/Wire.cpp b/libraries/Wire/Wire.cpp index f1df222f7..af3cf952d 100644 --- a/libraries/Wire/Wire.cpp +++ b/libraries/Wire/Wire.cpp @@ -21,7 +21,28 @@ void arduino::ZephyrI2C::begin(uint8_t slaveAddr) { void arduino::ZephyrI2C::end() {} -void arduino::ZephyrI2C::setClock(uint32_t freq) {} +void arduino::ZephyrI2C::setClock(uint32_t freq) { + uint8_t speed = I2C_SPEED_STANDARD; + if(freq > 0x06u ) { + if(freq == 100000) { + speed = I2C_SPEED_STANDARD; + } else if(freq == 400000) { + speed = I2C_SPEED_FAST; + } else if(freq == 1000000) { + speed = I2C_SPEED_FAST_PLUS; + } else { + speed = I2C_SPEED_STANDARD; + } + } else { + speed = (uint8_t) freq; + } + uint32_t i2c_cfg = I2C_MODE_CONTROLLER | + I2C_SPEED_SET(speed); + + if (i2c_configure(i2c_dev, i2c_cfg)) { + //Serial.println("Failed to configure i2c interface."); + } +} void arduino::ZephyrI2C::beginTransmission(uint8_t address) { // TODO for ADS1115 _address = address; From 127be40b1c95cf080d41c28121382cf545f75ff1 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Thu, 24 Jul 2025 16:53:36 +0200 Subject: [PATCH 06/15] Wire: fix bug on read() backing storage The ringbuffer backing storage and the read buffer were the same buffer... memcpy over the same location has some nasty implications TODO: move to more complex APIs (like i2c_transfer) to properly implement stop bit --- libraries/Wire/Wire.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/libraries/Wire/Wire.cpp b/libraries/Wire/Wire.cpp index af3cf952d..0453db62d 100644 --- a/libraries/Wire/Wire.cpp +++ b/libraries/Wire/Wire.cpp @@ -63,12 +63,13 @@ uint8_t arduino::ZephyrI2C::endTransmission(void) { // TODO for ADS1115 size_t arduino::ZephyrI2C::requestFrom(uint8_t address, size_t len, bool stopBit) { - int ret = i2c_read(i2c_dev, rxRingBuffer.buffer, len, address); + uint8_t buf[len]; + int ret = i2c_read(i2c_dev, buf, len, address); if (ret != 0) { return 0; } - ret = ring_buf_put(&rxRingBuffer.rb, rxRingBuffer.buffer, len); + ret = ring_buf_put(&rxRingBuffer.rb, buf, len); if (ret == 0) { return 0; @@ -96,19 +97,19 @@ size_t arduino::ZephyrI2C::write(const uint8_t *buffer, size_t size) { int arduino::ZephyrI2C::read() { uint8_t buf[1]; - if (ring_buf_peek(&rxRingBuffer.rb, buf, 1) > 0) { + if (ring_buf_size_get(&rxRingBuffer.rb)) { int ret = ring_buf_get(&rxRingBuffer.rb, buf, 1); if (ret == 0) { - return 0; + return -1; } return (int)buf[0]; } - return EXIT_FAILURE; + return -1; } -int arduino::ZephyrI2C::available() { // TODO for ADS1115 - return ring_buf_size_get(&rxRingBuffer.rb); // ret 0 if empty - } +int arduino::ZephyrI2C::available() { + return ring_buf_size_get(&rxRingBuffer.rb); +} int arduino::ZephyrI2C::peek() { uint8_t buf[1]; From 0d9f4cf0836480ba8cc142221ac4417e7956fc9d Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Tue, 29 Jul 2025 19:18:53 +0200 Subject: [PATCH 07/15] libraries/Wire: Add support for target mode. - Add support for I2C target mode. - Fix buffer overflows, bad return values etc.. Signed-off-by: iabdalkader --- libraries/Wire/Wire.cpp | 242 ++++++++++++++++++++++++++++------------ libraries/Wire/Wire.h | 29 +++-- 2 files changed, 191 insertions(+), 80 deletions(-) diff --git a/libraries/Wire/Wire.cpp b/libraries/Wire/Wire.cpp index 0453db62d..0fd34ff6f 100644 --- a/libraries/Wire/Wire.cpp +++ b/libraries/Wire/Wire.cpp @@ -5,104 +5,146 @@ */ #include +#include #include -arduino::ZephyrI2C::ZephyrI2C(const struct device *i2c) : i2c_dev(i2c) -{ +// Helper function to get ZephyrI2C instance from config pointer. +static arduino::ZephyrI2C* getInstance(struct i2c_target_config *config) { + return reinterpret_cast( + reinterpret_cast(config) - offsetof(arduino::ZephyrI2C, i2c_cfg) + ); +} + +static int i2c_target_stop_cb(struct i2c_target_config *config) { + arduino::ZephyrI2C *instance = getInstance(config); + return instance->stopCallback(config); +} + +static int i2c_target_write_requested_cb(struct i2c_target_config *config) { + arduino::ZephyrI2C *instance = getInstance(config); + return instance->writeRequestedCallback(config); +} + +static int i2c_target_write_received_cb(struct i2c_target_config *config, uint8_t val) { + arduino::ZephyrI2C *instance = getInstance(config); + return instance->writeReceivedCallback(config, val); +} + +static int i2c_target_read_requested_cb(struct i2c_target_config *config, uint8_t *val) { + arduino::ZephyrI2C *instance = getInstance(config); + return instance->readRequestedCallback(config, val); +} + +static int i2c_target_read_processed_cb(struct i2c_target_config *config, uint8_t *val) { + arduino::ZephyrI2C *instance = getInstance(config); + return instance->readProcessedCallback(config, val); +} + +// I2C target callback structure. +static struct i2c_target_callbacks target_callbacks = { + .write_requested = i2c_target_write_requested_cb, + .read_requested = i2c_target_read_requested_cb, + .write_received = i2c_target_write_received_cb, + .read_processed = i2c_target_read_processed_cb, + .stop = i2c_target_stop_cb, +}; + +arduino::ZephyrI2C::ZephyrI2C(const struct device *i2c) : i2c_dev(i2c), i2c_cfg({0}) { + ring_buf_init(&txRingBuffer.rb, sizeof(txRingBuffer.buffer), txRingBuffer.buffer); + ring_buf_init(&rxRingBuffer.rb, sizeof(rxRingBuffer.buffer), rxRingBuffer.buffer); } void arduino::ZephyrI2C::begin() { - ring_buf_init(&rxRingBuffer.rb, sizeof(rxRingBuffer.buffer), rxRingBuffer.buffer); + } void arduino::ZephyrI2C::begin(uint8_t slaveAddr) { + i2c_cfg.address = slaveAddr; + i2c_cfg.callbacks = &target_callbacks; + // Register I2C target + i2c_target_register(i2c_dev, &i2c_cfg); } -void arduino::ZephyrI2C::end() {} +void arduino::ZephyrI2C::end() { + // Unregister I2C target + if (i2c_cfg.address) { + i2c_target_unregister(i2c_dev, &i2c_cfg); + memset(&i2c_cfg, 0, sizeof(i2c_cfg)); + } +} void arduino::ZephyrI2C::setClock(uint32_t freq) { - uint8_t speed = I2C_SPEED_STANDARD; - if(freq > 0x06u ) { - if(freq == 100000) { - speed = I2C_SPEED_STANDARD; - } else if(freq == 400000) { - speed = I2C_SPEED_FAST; - } else if(freq == 1000000) { - speed = I2C_SPEED_FAST_PLUS; - } else { - speed = I2C_SPEED_STANDARD; - } - } else { - speed = (uint8_t) freq; - } - uint32_t i2c_cfg = I2C_MODE_CONTROLLER | - I2C_SPEED_SET(speed); - - if (i2c_configure(i2c_dev, i2c_cfg)) { - //Serial.println("Failed to configure i2c interface."); - } -} - -void arduino::ZephyrI2C::beginTransmission(uint8_t address) { // TODO for ADS1115 + uint8_t speed; + + if (freq == 100000) { + speed = I2C_SPEED_STANDARD; + } else if (freq == 400000) { + speed = I2C_SPEED_FAST; + } else if (freq == 1000000) { + speed = I2C_SPEED_FAST_PLUS; + } else { + speed = I2C_SPEED_STANDARD; + } + + i2c_configure(i2c_dev, I2C_SPEED_SET(speed) | I2C_MODE_CONTROLLER); +} + +void arduino::ZephyrI2C::beginTransmission(uint8_t address) { _address = address; - usedTxBuffer = 0; + ring_buf_reset(&txRingBuffer.rb); + ring_buf_reset(&rxRingBuffer.rb); } uint8_t arduino::ZephyrI2C::endTransmission(bool stopBit) { - int ret = i2c_write(i2c_dev, txBuffer, usedTxBuffer, _address); - if (ret) { - return 1; // fail - } - return 0; + int ret = -EIO; + uint8_t *buf = NULL; + size_t max = ring_buf_capacity_get(&txRingBuffer.rb); + size_t len = ring_buf_get_claim(&txRingBuffer.rb, &buf, max); + + ret = i2c_write(i2c_dev, buf, len, _address); + + // Must be called even if 0 bytes claimed. + ring_buf_get_finish(&txRingBuffer.rb, len); + + return ret ? 1 : 0; } -uint8_t arduino::ZephyrI2C::endTransmission(void) { // TODO for ADS1115 +uint8_t arduino::ZephyrI2C::endTransmission(void) { return endTransmission(true); } -size_t arduino::ZephyrI2C::requestFrom(uint8_t address, size_t len, - bool stopBit) { - uint8_t buf[len]; - int ret = i2c_read(i2c_dev, buf, len, address); - if (ret != 0) - { - return 0; - } - ret = ring_buf_put(&rxRingBuffer.rb, buf, len); - if (ret == 0) - { - return 0; +size_t arduino::ZephyrI2C::requestFrom(uint8_t address, size_t len_in, bool stopBit) { + int ret = -EIO; + uint8_t *buf = NULL; + size_t len = ring_buf_put_claim(&rxRingBuffer.rb, &buf, len_in); + + if (len && buf) { + ret = i2c_read(i2c_dev, buf, len, address); } - return len; + + // Must be called even if 0 bytes claimed. + ring_buf_put_finish(&rxRingBuffer.rb, len); + + return ret ? 0 : len; } -size_t arduino::ZephyrI2C::requestFrom(uint8_t address, size_t len) { // TODO for ADS1115 +size_t arduino::ZephyrI2C::requestFrom(uint8_t address, size_t len) { return requestFrom(address, len, true); } -size_t arduino::ZephyrI2C::write(uint8_t data) { // TODO for ADS1115 - txBuffer[usedTxBuffer++] = data; - return 1; +size_t arduino::ZephyrI2C::write(uint8_t data) { + return ring_buf_put(&txRingBuffer.rb, &data, 1); } size_t arduino::ZephyrI2C::write(const uint8_t *buffer, size_t size) { - if (usedTxBuffer + size > 256) { - size = 256 - usedTxBuffer; - } - memcpy(txBuffer + usedTxBuffer, buffer, size); - usedTxBuffer += size; - return size; + return ring_buf_put(&txRingBuffer.rb, buffer, size); } int arduino::ZephyrI2C::read() { - uint8_t buf[1]; - if (ring_buf_size_get(&rxRingBuffer.rb)) { - int ret = ring_buf_get(&rxRingBuffer.rb, buf, 1); - if (ret == 0) { - return -1; - } - return (int)buf[0]; + uint8_t buf; + if (ring_buf_get(&rxRingBuffer.rb, &buf, 1)) { + return (int) buf; } return -1; } @@ -112,18 +154,74 @@ int arduino::ZephyrI2C::available() { } int arduino::ZephyrI2C::peek() { - uint8_t buf[1]; - int bytes_read = ring_buf_peek(&rxRingBuffer.rb, buf, 1); - if (bytes_read == 0){ - return 0; + uint8_t buf; + if (ring_buf_peek(&rxRingBuffer.rb, &buf, 1)) { + return (int) buf; } - return (int)buf[0]; + return -1; +} + +void arduino::ZephyrI2C::flush() { + +} + +void arduino::ZephyrI2C::onReceive(voidFuncPtrParamInt cb) { + onReceiveCb = cb; +} + +void arduino::ZephyrI2C::onRequest(voidFuncPtr cb) { + onRequestCb = cb; +} + +int arduino::ZephyrI2C::writeRequestedCallback(struct i2c_target_config *config) { + // Reset the buffer on write requests. + ring_buf_reset(&rxRingBuffer.rb); + return 0; +} + +int arduino::ZephyrI2C::writeReceivedCallback(struct i2c_target_config *config, uint8_t val) { + size_t len = ring_buf_size_get(&rxRingBuffer.rb); + size_t max = ring_buf_capacity_get(&rxRingBuffer.rb); + + // If the buffer is about to overflow, invoke the callback + // with the current length. + if (onReceiveCb && ((len + 1) > max)) { + onReceiveCb(len); + } + + return ring_buf_put(&rxRingBuffer.rb, &val, 1) ? 0 : -1; } -void arduino::ZephyrI2C::flush() {} +int arduino::ZephyrI2C::readRequestedCallback(struct i2c_target_config *config, uint8_t *val) { + // Reset the buffer on read requests. + ring_buf_reset(&txRingBuffer.rb); + + if (onRequestCb) { + onRequestCb(); + } + + return readProcessedCallback(config, val); +} -void arduino::ZephyrI2C::onReceive(voidFuncPtrParamInt cb) {} -void arduino::ZephyrI2C::onRequest(voidFuncPtr cb) {} +int arduino::ZephyrI2C::readProcessedCallback(struct i2c_target_config *config, uint8_t *val) { + *val = 0xFF; + ring_buf_get(&txRingBuffer.rb, val, 1); + // Returning a negative value here is not handled gracefully and + // causes the target/board to stop responding (at least with ST). + return 0; +} + +int arduino::ZephyrI2C::stopCallback(struct i2c_target_config *config) { + // If the RX buffer is not empty invoke the callback with the + // remaining data length. + if (onReceiveCb) { + size_t len = ring_buf_size_get(&rxRingBuffer.rb); + if (len) { + onReceiveCb(len); + } + } + return 0; +} #if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), i2cs) #if (DT_PROP_LEN(DT_PATH(zephyr_user), i2cs) > 1) diff --git a/libraries/Wire/Wire.h b/libraries/Wire/Wire.h index 6e289f8c1..cb5fb0c77 100644 --- a/libraries/Wire/Wire.h +++ b/libraries/Wire/Wire.h @@ -15,6 +15,11 @@ typedef void (*voidFuncPtrParamInt)(int); namespace arduino { +struct i2c_ring { + struct ring_buf rb; + uint8_t buffer[256]; +}; + class ZephyrI2C : public HardwareI2C { public: ZephyrI2C(const struct device* i2c); @@ -43,16 +48,24 @@ class ZephyrI2C : public HardwareI2C { virtual void flush(); virtual int available(); + // I2C target callbacks + int writeRequestedCallback(struct i2c_target_config *config); + int writeReceivedCallback(struct i2c_target_config *config, uint8_t val); + int readRequestedCallback(struct i2c_target_config *config, uint8_t *val); + int readProcessedCallback(struct i2c_target_config *config, uint8_t *val); + int stopCallback(struct i2c_target_config *config); + + struct i2c_target_config i2c_cfg; + private: int _address; - uint8_t txBuffer[256]; - uint32_t usedTxBuffer; - struct rx_ring_buf{ - struct ring_buf rb; - uint8_t buffer[256]; - }; - struct rx_ring_buf rxRingBuffer; - const struct device* i2c_dev; + + struct i2c_ring txRingBuffer; + struct i2c_ring rxRingBuffer; + const struct device *i2c_dev; + + voidFuncPtr onRequestCb = NULL; + voidFuncPtrParamInt onReceiveCb = NULL; }; } // namespace arduino From 2ec7fdb03de29c18a90b4fb81b3b3f1aa2745460 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Thu, 28 Aug 2025 15:41:30 +0200 Subject: [PATCH 08/15] misc: Format repo using clang-format. Signed-off-by: iabdalkader --- libraries/SPI/SPI.cpp | 172 ++++++++++++++++--------------- libraries/SPI/SPI.h | 44 ++++---- libraries/Wire/Wire.cpp | 219 ++++++++++++++++++++-------------------- libraries/Wire/Wire.h | 74 +++++++------- 4 files changed, 261 insertions(+), 248 deletions(-) diff --git a/libraries/SPI/SPI.cpp b/libraries/SPI/SPI.cpp index 897d57f2a..8dd61f21e 100644 --- a/libraries/SPI/SPI.cpp +++ b/libraries/SPI/SPI.cpp @@ -8,69 +8,70 @@ #include "zephyrInternal.h" #include -arduino::ZephyrSPI::ZephyrSPI(const struct device *spi) : spi_dev(spi) {} +arduino::ZephyrSPI::ZephyrSPI(const struct device *spi) : spi_dev(spi) { +} uint8_t arduino::ZephyrSPI::transfer(uint8_t data) { - int ret; - uint8_t rx; - const struct spi_buf tx_buf = {.buf = &data, .len = sizeof(data)}; - const struct spi_buf_set tx_buf_set = { - .buffers = &tx_buf, - .count = 1, - }; - const struct spi_buf rx_buf = {.buf = &rx, .len = sizeof(rx)}; - const struct spi_buf_set rx_buf_set = { - .buffers = &rx_buf, - .count = 1, - }; - - ret = spi_transceive(spi_dev, &config, &tx_buf_set, &rx_buf_set); - if (ret < 0) { - return 0; - } - - return rx; + int ret; + uint8_t rx; + const struct spi_buf tx_buf = {.buf = &data, .len = sizeof(data)}; + const struct spi_buf_set tx_buf_set = { + .buffers = &tx_buf, + .count = 1, + }; + const struct spi_buf rx_buf = {.buf = &rx, .len = sizeof(rx)}; + const struct spi_buf_set rx_buf_set = { + .buffers = &rx_buf, + .count = 1, + }; + + ret = spi_transceive(spi_dev, &config, &tx_buf_set, &rx_buf_set); + if (ret < 0) { + return 0; + } + + return rx; } uint16_t arduino::ZephyrSPI::transfer16(uint16_t data) { - int ret; - uint16_t rx; - const struct spi_buf tx_buf = {.buf = &data, .len = sizeof(data)}; - const struct spi_buf_set tx_buf_set = { - .buffers = &tx_buf, - .count = 1, - }; - const struct spi_buf rx_buf = {.buf = &rx, .len = sizeof(rx)}; - const struct spi_buf_set rx_buf_set = { - .buffers = &rx_buf, - .count = 1, - }; - - ret = spi_transceive(spi_dev, &config16, &tx_buf_set, &rx_buf_set); - if (ret < 0) { - return 0; - } - - return rx; + int ret; + uint16_t rx; + const struct spi_buf tx_buf = {.buf = &data, .len = sizeof(data)}; + const struct spi_buf_set tx_buf_set = { + .buffers = &tx_buf, + .count = 1, + }; + const struct spi_buf rx_buf = {.buf = &rx, .len = sizeof(rx)}; + const struct spi_buf_set rx_buf_set = { + .buffers = &rx_buf, + .count = 1, + }; + + ret = spi_transceive(spi_dev, &config16, &tx_buf_set, &rx_buf_set); + if (ret < 0) { + return 0; + } + + return rx; } void arduino::ZephyrSPI::transfer(void *buf, size_t count) { - int ret; - const struct spi_buf tx_buf = {.buf = buf, .len = count}; - const struct spi_buf_set tx_buf_set = { - .buffers = &tx_buf, - .count = 1, - }; - - uint8_t rx[count]; - const struct spi_buf rx_buf = {.buf = &rx, .len = count}; - const struct spi_buf_set rx_buf_set = { - .buffers = &rx_buf, - .count = 1, - }; - - spi_transceive(spi_dev, &config, &tx_buf_set, &rx_buf_set); - memcpy(buf, rx, count); + int ret; + const struct spi_buf tx_buf = {.buf = buf, .len = count}; + const struct spi_buf_set tx_buf_set = { + .buffers = &tx_buf, + .count = 1, + }; + + uint8_t rx[count]; + const struct spi_buf rx_buf = {.buf = &rx, .len = count}; + const struct spi_buf_set rx_buf_set = { + .buffers = &rx_buf, + .count = 1, + }; + + spi_transceive(spi_dev, &config, &tx_buf_set, &rx_buf_set); + memcpy(buf, rx, count); } void arduino::ZephyrSPI::usingInterrupt(int interruptNumber) { @@ -84,41 +85,52 @@ void arduino::ZephyrSPI::notUsingInterrupt(int interruptNumber) { #endif void arduino::ZephyrSPI::beginTransaction(SPISettings settings) { - memset(&config, 0, sizeof(config)); - memset(&config16, 0, sizeof(config16)); - config.frequency = settings.getClockFreq() > SPI_MIN_CLOCK_FEQUENCY ? settings.getClockFreq() : SPI_MIN_CLOCK_FEQUENCY; - config16.frequency = config.frequency; - - auto mode = SPI_MODE_CPOL | SPI_MODE_CPHA; - switch (settings.getDataMode()) { - case SPI_MODE0: - mode = 0; break; - case SPI_MODE1: - mode = SPI_MODE_CPHA; break; - case SPI_MODE2: - mode = SPI_MODE_CPOL; break; - case SPI_MODE3: - mode = SPI_MODE_CPOL | SPI_MODE_CPHA; break; - } - config.operation = SPI_WORD_SET(8) | (settings.getBitOrder() == MSBFIRST ? SPI_TRANSFER_MSB : SPI_TRANSFER_LSB) | mode; - config16.operation = SPI_WORD_SET(16) | (settings.getBitOrder() == MSBFIRST ? SPI_TRANSFER_MSB : SPI_TRANSFER_LSB) | mode; + memset(&config, 0, sizeof(config)); + memset(&config16, 0, sizeof(config16)); + config.frequency = settings.getClockFreq() > SPI_MIN_CLOCK_FEQUENCY ? settings.getClockFreq() : + SPI_MIN_CLOCK_FEQUENCY; + config16.frequency = config.frequency; + + auto mode = SPI_MODE_CPOL | SPI_MODE_CPHA; + switch (settings.getDataMode()) { + case SPI_MODE0: + mode = 0; + break; + case SPI_MODE1: + mode = SPI_MODE_CPHA; + break; + case SPI_MODE2: + mode = SPI_MODE_CPOL; + break; + case SPI_MODE3: + mode = SPI_MODE_CPOL | SPI_MODE_CPHA; + break; + } + config.operation = SPI_WORD_SET(8) | + (settings.getBitOrder() == MSBFIRST ? SPI_TRANSFER_MSB : SPI_TRANSFER_LSB) | + mode; + config16.operation = + SPI_WORD_SET(16) | + (settings.getBitOrder() == MSBFIRST ? SPI_TRANSFER_MSB : SPI_TRANSFER_LSB) | mode; } void arduino::ZephyrSPI::endTransaction(void) { - spi_release(spi_dev, &config); + spi_release(spi_dev, &config); } -void arduino::ZephyrSPI::attachInterrupt() {} - -void arduino::ZephyrSPI::detachInterrupt() {} +void arduino::ZephyrSPI::attachInterrupt() { +} +void arduino::ZephyrSPI::detachInterrupt() { +} void arduino::ZephyrSPI::begin() { - beginTransaction(SPISettings()); - endTransaction(); + beginTransaction(SPISettings()); + endTransaction(); } -void arduino::ZephyrSPI::end() {} +void arduino::ZephyrSPI::end() { +} #if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), spis) #if (DT_PROP_LEN(DT_PATH(zephyr_user), spis) > 1) diff --git a/libraries/SPI/SPI.h b/libraries/SPI/SPI.h index ec3b68695..95c41ce25 100644 --- a/libraries/SPI/SPI.h +++ b/libraries/SPI/SPI.h @@ -19,43 +19,43 @@ #define CPOL 3 #define MSTR 4 #define DORD 5 -#define SPE 6 +#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, \ +#define INTERRUPT_COUNT \ + DT_FOREACH_PROP_ELEM_SEP(DT_PATH(zephyr_user), digital_pin_gpios, \ INTERRUPT_HELPER, (+)) namespace arduino { class ZephyrSPI : public HardwareSPI { public: - ZephyrSPI(const struct device *spi); + ZephyrSPI(const struct device *spi); - virtual uint8_t transfer(uint8_t data); - virtual uint16_t transfer16(uint16_t data); - virtual void transfer(void *buf, size_t count); + virtual uint8_t transfer(uint8_t data); + virtual uint16_t transfer16(uint16_t data); + virtual void transfer(void *buf, size_t count); - // Transaction Functions - virtual void usingInterrupt(int interruptNumber); - virtual void notUsingInterrupt(int interruptNumber); - virtual void beginTransaction(SPISettings settings); - virtual void endTransaction(void); + // Transaction Functions + virtual void usingInterrupt(int interruptNumber); + virtual void notUsingInterrupt(int interruptNumber); + virtual void beginTransaction(SPISettings settings); + virtual void endTransaction(void); - // SPI Configuration methods - virtual void attachInterrupt(); - virtual void detachInterrupt(); + // SPI Configuration methods + virtual void attachInterrupt(); + virtual void detachInterrupt(); - virtual void begin(); - virtual void end(); + virtual void begin(); + virtual void end(); protected: - const struct device *spi_dev; - struct spi_config config; - struct spi_config config16; - int interrupt[INTERRUPT_COUNT]; - size_t interrupt_pos = 0; + const struct device *spi_dev; + struct spi_config config; + struct spi_config config16; + int interrupt[INTERRUPT_COUNT]; + size_t interrupt_pos = 0; }; } // namespace arduino diff --git a/libraries/Wire/Wire.cpp b/libraries/Wire/Wire.cpp index 0fd34ff6f..18ec6140c 100644 --- a/libraries/Wire/Wire.cpp +++ b/libraries/Wire/Wire.cpp @@ -9,218 +9,215 @@ #include // Helper function to get ZephyrI2C instance from config pointer. -static arduino::ZephyrI2C* getInstance(struct i2c_target_config *config) { - return reinterpret_cast( - reinterpret_cast(config) - offsetof(arduino::ZephyrI2C, i2c_cfg) - ); +static arduino::ZephyrI2C *getInstance(struct i2c_target_config *config) { + return reinterpret_cast(reinterpret_cast(config) - + offsetof(arduino::ZephyrI2C, i2c_cfg)); } static int i2c_target_stop_cb(struct i2c_target_config *config) { - arduino::ZephyrI2C *instance = getInstance(config); - return instance->stopCallback(config); + arduino::ZephyrI2C *instance = getInstance(config); + return instance->stopCallback(config); } static int i2c_target_write_requested_cb(struct i2c_target_config *config) { - arduino::ZephyrI2C *instance = getInstance(config); - return instance->writeRequestedCallback(config); + arduino::ZephyrI2C *instance = getInstance(config); + return instance->writeRequestedCallback(config); } static int i2c_target_write_received_cb(struct i2c_target_config *config, uint8_t val) { - arduino::ZephyrI2C *instance = getInstance(config); - return instance->writeReceivedCallback(config, val); + arduino::ZephyrI2C *instance = getInstance(config); + return instance->writeReceivedCallback(config, val); } static int i2c_target_read_requested_cb(struct i2c_target_config *config, uint8_t *val) { - arduino::ZephyrI2C *instance = getInstance(config); - return instance->readRequestedCallback(config, val); + arduino::ZephyrI2C *instance = getInstance(config); + return instance->readRequestedCallback(config, val); } static int i2c_target_read_processed_cb(struct i2c_target_config *config, uint8_t *val) { - arduino::ZephyrI2C *instance = getInstance(config); - return instance->readProcessedCallback(config, val); + arduino::ZephyrI2C *instance = getInstance(config); + return instance->readProcessedCallback(config, val); } // I2C target callback structure. static struct i2c_target_callbacks target_callbacks = { - .write_requested = i2c_target_write_requested_cb, - .read_requested = i2c_target_read_requested_cb, - .write_received = i2c_target_write_received_cb, - .read_processed = i2c_target_read_processed_cb, - .stop = i2c_target_stop_cb, + .write_requested = i2c_target_write_requested_cb, + .read_requested = i2c_target_read_requested_cb, + .write_received = i2c_target_write_received_cb, + .read_processed = i2c_target_read_processed_cb, + .stop = i2c_target_stop_cb, }; arduino::ZephyrI2C::ZephyrI2C(const struct device *i2c) : i2c_dev(i2c), i2c_cfg({0}) { - ring_buf_init(&txRingBuffer.rb, sizeof(txRingBuffer.buffer), txRingBuffer.buffer); - ring_buf_init(&rxRingBuffer.rb, sizeof(rxRingBuffer.buffer), rxRingBuffer.buffer); + ring_buf_init(&txRingBuffer.rb, sizeof(txRingBuffer.buffer), txRingBuffer.buffer); + ring_buf_init(&rxRingBuffer.rb, sizeof(rxRingBuffer.buffer), rxRingBuffer.buffer); } void arduino::ZephyrI2C::begin() { - } void arduino::ZephyrI2C::begin(uint8_t slaveAddr) { - i2c_cfg.address = slaveAddr; - i2c_cfg.callbacks = &target_callbacks; + i2c_cfg.address = slaveAddr; + i2c_cfg.callbacks = &target_callbacks; - // Register I2C target - i2c_target_register(i2c_dev, &i2c_cfg); + // Register I2C target + i2c_target_register(i2c_dev, &i2c_cfg); } void arduino::ZephyrI2C::end() { - // Unregister I2C target - if (i2c_cfg.address) { - i2c_target_unregister(i2c_dev, &i2c_cfg); - memset(&i2c_cfg, 0, sizeof(i2c_cfg)); - } + // Unregister I2C target + if (i2c_cfg.address) { + i2c_target_unregister(i2c_dev, &i2c_cfg); + memset(&i2c_cfg, 0, sizeof(i2c_cfg)); + } } void arduino::ZephyrI2C::setClock(uint32_t freq) { - uint8_t speed; + uint8_t speed; - if (freq == 100000) { - speed = I2C_SPEED_STANDARD; - } else if (freq == 400000) { - speed = I2C_SPEED_FAST; - } else if (freq == 1000000) { - speed = I2C_SPEED_FAST_PLUS; - } else { - speed = I2C_SPEED_STANDARD; - } + if (freq == 100000) { + speed = I2C_SPEED_STANDARD; + } else if (freq == 400000) { + speed = I2C_SPEED_FAST; + } else if (freq == 1000000) { + speed = I2C_SPEED_FAST_PLUS; + } else { + speed = I2C_SPEED_STANDARD; + } - i2c_configure(i2c_dev, I2C_SPEED_SET(speed) | I2C_MODE_CONTROLLER); + i2c_configure(i2c_dev, I2C_SPEED_SET(speed) | I2C_MODE_CONTROLLER); } void arduino::ZephyrI2C::beginTransmission(uint8_t address) { - _address = address; - ring_buf_reset(&txRingBuffer.rb); - ring_buf_reset(&rxRingBuffer.rb); + _address = address; + ring_buf_reset(&txRingBuffer.rb); + ring_buf_reset(&rxRingBuffer.rb); } uint8_t arduino::ZephyrI2C::endTransmission(bool stopBit) { - int ret = -EIO; - uint8_t *buf = NULL; - size_t max = ring_buf_capacity_get(&txRingBuffer.rb); - size_t len = ring_buf_get_claim(&txRingBuffer.rb, &buf, max); + int ret = -EIO; + uint8_t *buf = NULL; + size_t max = ring_buf_capacity_get(&txRingBuffer.rb); + size_t len = ring_buf_get_claim(&txRingBuffer.rb, &buf, max); - ret = i2c_write(i2c_dev, buf, len, _address); + ret = i2c_write(i2c_dev, buf, len, _address); - // Must be called even if 0 bytes claimed. - ring_buf_get_finish(&txRingBuffer.rb, len); + // Must be called even if 0 bytes claimed. + ring_buf_get_finish(&txRingBuffer.rb, len); - return ret ? 1 : 0; + return ret ? 1 : 0; } uint8_t arduino::ZephyrI2C::endTransmission(void) { - return endTransmission(true); + return endTransmission(true); } size_t arduino::ZephyrI2C::requestFrom(uint8_t address, size_t len_in, bool stopBit) { - int ret = -EIO; - uint8_t *buf = NULL; - size_t len = ring_buf_put_claim(&rxRingBuffer.rb, &buf, len_in); + int ret = -EIO; + uint8_t *buf = NULL; + size_t len = ring_buf_put_claim(&rxRingBuffer.rb, &buf, len_in); - if (len && buf) { - ret = i2c_read(i2c_dev, buf, len, address); - } + if (len && buf) { + ret = i2c_read(i2c_dev, buf, len, address); + } - // Must be called even if 0 bytes claimed. - ring_buf_put_finish(&rxRingBuffer.rb, len); + // Must be called even if 0 bytes claimed. + ring_buf_put_finish(&rxRingBuffer.rb, len); - return ret ? 0 : len; + return ret ? 0 : len; } size_t arduino::ZephyrI2C::requestFrom(uint8_t address, size_t len) { - return requestFrom(address, len, true); + return requestFrom(address, len, true); } size_t arduino::ZephyrI2C::write(uint8_t data) { - return ring_buf_put(&txRingBuffer.rb, &data, 1); + return ring_buf_put(&txRingBuffer.rb, &data, 1); } size_t arduino::ZephyrI2C::write(const uint8_t *buffer, size_t size) { - return ring_buf_put(&txRingBuffer.rb, buffer, size); + return ring_buf_put(&txRingBuffer.rb, buffer, size); } int arduino::ZephyrI2C::read() { - uint8_t buf; - if (ring_buf_get(&rxRingBuffer.rb, &buf, 1)) { - return (int) buf; - } - return -1; + uint8_t buf; + if (ring_buf_get(&rxRingBuffer.rb, &buf, 1)) { + return (int)buf; + } + return -1; } int arduino::ZephyrI2C::available() { - return ring_buf_size_get(&rxRingBuffer.rb); + return ring_buf_size_get(&rxRingBuffer.rb); } int arduino::ZephyrI2C::peek() { - uint8_t buf; - if (ring_buf_peek(&rxRingBuffer.rb, &buf, 1)) { - return (int) buf; - } - return -1; + uint8_t buf; + if (ring_buf_peek(&rxRingBuffer.rb, &buf, 1)) { + return (int)buf; + } + return -1; } void arduino::ZephyrI2C::flush() { - } void arduino::ZephyrI2C::onReceive(voidFuncPtrParamInt cb) { - onReceiveCb = cb; + onReceiveCb = cb; } void arduino::ZephyrI2C::onRequest(voidFuncPtr cb) { - onRequestCb = cb; + onRequestCb = cb; } int arduino::ZephyrI2C::writeRequestedCallback(struct i2c_target_config *config) { - // Reset the buffer on write requests. - ring_buf_reset(&rxRingBuffer.rb); - return 0; + // Reset the buffer on write requests. + ring_buf_reset(&rxRingBuffer.rb); + return 0; } int arduino::ZephyrI2C::writeReceivedCallback(struct i2c_target_config *config, uint8_t val) { - size_t len = ring_buf_size_get(&rxRingBuffer.rb); - size_t max = ring_buf_capacity_get(&rxRingBuffer.rb); + size_t len = ring_buf_size_get(&rxRingBuffer.rb); + size_t max = ring_buf_capacity_get(&rxRingBuffer.rb); - // If the buffer is about to overflow, invoke the callback - // with the current length. - if (onReceiveCb && ((len + 1) > max)) { - onReceiveCb(len); - } + // If the buffer is about to overflow, invoke the callback + // with the current length. + if (onReceiveCb && ((len + 1) > max)) { + onReceiveCb(len); + } - return ring_buf_put(&rxRingBuffer.rb, &val, 1) ? 0 : -1; + return ring_buf_put(&rxRingBuffer.rb, &val, 1) ? 0 : -1; } int arduino::ZephyrI2C::readRequestedCallback(struct i2c_target_config *config, uint8_t *val) { - // Reset the buffer on read requests. - ring_buf_reset(&txRingBuffer.rb); + // Reset the buffer on read requests. + ring_buf_reset(&txRingBuffer.rb); - if (onRequestCb) { - onRequestCb(); - } + if (onRequestCb) { + onRequestCb(); + } - return readProcessedCallback(config, val); + return readProcessedCallback(config, val); } int arduino::ZephyrI2C::readProcessedCallback(struct i2c_target_config *config, uint8_t *val) { - *val = 0xFF; - ring_buf_get(&txRingBuffer.rb, val, 1); - // Returning a negative value here is not handled gracefully and - // causes the target/board to stop responding (at least with ST). - return 0; + *val = 0xFF; + ring_buf_get(&txRingBuffer.rb, val, 1); + // Returning a negative value here is not handled gracefully and + // causes the target/board to stop responding (at least with ST). + return 0; } int arduino::ZephyrI2C::stopCallback(struct i2c_target_config *config) { - // If the RX buffer is not empty invoke the callback with the - // remaining data length. - if (onReceiveCb) { - size_t len = ring_buf_size_get(&rxRingBuffer.rb); - if (len) { - onReceiveCb(len); - } - } - return 0; + // If the RX buffer is not empty invoke the callback with the + // remaining data length. + if (onReceiveCb) { + size_t len = ring_buf_size_get(&rxRingBuffer.rb); + if (len) { + onReceiveCb(len); + } + } + return 0; } #if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), i2cs) diff --git a/libraries/Wire/Wire.h b/libraries/Wire/Wire.h index cb5fb0c77..47b126965 100644 --- a/libraries/Wire/Wire.h +++ b/libraries/Wire/Wire.h @@ -16,56 +16,60 @@ typedef void (*voidFuncPtrParamInt)(int); namespace arduino { struct i2c_ring { - struct ring_buf rb; - uint8_t buffer[256]; + struct ring_buf rb; + uint8_t buffer[256]; }; class ZephyrI2C : public HardwareI2C { public: - ZephyrI2C(const struct device* i2c); + ZephyrI2C(const struct device *i2c); - virtual void begin(); - virtual void end(); - virtual void begin(uint8_t address); - virtual void setClock(uint32_t freq); + virtual void begin(); + virtual void end(); + virtual void begin(uint8_t address); + virtual void setClock(uint32_t freq); - virtual void beginTransmission(uint8_t address); - virtual uint8_t endTransmission(bool stopBit); - virtual uint8_t endTransmission(void); + virtual void beginTransmission(uint8_t address); + virtual uint8_t endTransmission(bool stopBit); + virtual uint8_t endTransmission(void); - virtual size_t requestFrom(uint8_t address, size_t len, bool stopBit); - virtual size_t requestFrom(uint8_t address, size_t len); + virtual size_t requestFrom(uint8_t address, size_t len, bool stopBit); + virtual size_t requestFrom(uint8_t address, size_t len); - virtual void onReceive(void (*)(int)); - virtual void onRequest(void (*)(void)); + virtual void onReceive(void (*)(int)); + virtual void onRequest(void (*)(void)); - virtual size_t write(uint8_t data); - virtual size_t write(int data) { return write((uint8_t)data); }; - virtual size_t write(const uint8_t *buffer, size_t size); - using Print::write; - virtual int read(); - virtual int peek(); - virtual void flush(); - virtual int available(); + virtual size_t write(uint8_t data); - // I2C target callbacks - int writeRequestedCallback(struct i2c_target_config *config); - int writeReceivedCallback(struct i2c_target_config *config, uint8_t val); - int readRequestedCallback(struct i2c_target_config *config, uint8_t *val); - int readProcessedCallback(struct i2c_target_config *config, uint8_t *val); - int stopCallback(struct i2c_target_config *config); + virtual size_t write(int data) { + return write((uint8_t)data); + }; - struct i2c_target_config i2c_cfg; + virtual size_t write(const uint8_t *buffer, size_t size); + using Print::write; + virtual int read(); + virtual int peek(); + virtual void flush(); + virtual int available(); + + // I2C target callbacks + int writeRequestedCallback(struct i2c_target_config *config); + int writeReceivedCallback(struct i2c_target_config *config, uint8_t val); + int readRequestedCallback(struct i2c_target_config *config, uint8_t *val); + int readProcessedCallback(struct i2c_target_config *config, uint8_t *val); + int stopCallback(struct i2c_target_config *config); + + struct i2c_target_config i2c_cfg; private: - int _address; + int _address; - struct i2c_ring txRingBuffer; - struct i2c_ring rxRingBuffer; - const struct device *i2c_dev; + struct i2c_ring txRingBuffer; + struct i2c_ring rxRingBuffer; + const struct device *i2c_dev; - voidFuncPtr onRequestCb = NULL; - voidFuncPtrParamInt onReceiveCb = NULL; + voidFuncPtr onRequestCb = NULL; + voidFuncPtrParamInt onReceiveCb = NULL; }; } // namespace arduino From df0afa812931ea60cb27bf4ae11198f80f2e1f23 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Wed, 17 Sep 2025 17:40:04 +0200 Subject: [PATCH 09/15] libraries/SPI: Add support for peripheral mode Signed-off-by: iabdalkader --- libraries/SPI/SPI.cpp | 100 +++++++++++++++++++----------------------- libraries/SPI/SPI.h | 11 +++++ 2 files changed, 55 insertions(+), 56 deletions(-) diff --git a/libraries/SPI/SPI.cpp b/libraries/SPI/SPI.cpp index 8dd61f21e..057b75d66 100644 --- a/libraries/SPI/SPI.cpp +++ b/libraries/SPI/SPI.cpp @@ -12,66 +12,42 @@ arduino::ZephyrSPI::ZephyrSPI(const struct device *spi) : spi_dev(spi) { } uint8_t arduino::ZephyrSPI::transfer(uint8_t data) { - int ret; - uint8_t rx; - const struct spi_buf tx_buf = {.buf = &data, .len = sizeof(data)}; - const struct spi_buf_set tx_buf_set = { - .buffers = &tx_buf, - .count = 1, - }; - const struct spi_buf rx_buf = {.buf = &rx, .len = sizeof(rx)}; - const struct spi_buf_set rx_buf_set = { - .buffers = &rx_buf, - .count = 1, - }; - - ret = spi_transceive(spi_dev, &config, &tx_buf_set, &rx_buf_set); - if (ret < 0) { + uint8_t rx = data; + if (transfer(&rx, sizeof(rx), &config) < 0) { return 0; } - return rx; } uint16_t arduino::ZephyrSPI::transfer16(uint16_t data) { - int ret; - uint16_t rx; - const struct spi_buf tx_buf = {.buf = &data, .len = sizeof(data)}; - const struct spi_buf_set tx_buf_set = { - .buffers = &tx_buf, - .count = 1, - }; - const struct spi_buf rx_buf = {.buf = &rx, .len = sizeof(rx)}; - const struct spi_buf_set rx_buf_set = { - .buffers = &rx_buf, - .count = 1, - }; - - ret = spi_transceive(spi_dev, &config16, &tx_buf_set, &rx_buf_set); - if (ret < 0) { + uint16_t rx = data; + if (transfer(&rx, sizeof(rx), &config16) < 0) { return 0; } - return rx; } void arduino::ZephyrSPI::transfer(void *buf, size_t count) { + int ret = transfer(buf, count, &config); + (void)ret; +} + +int arduino::ZephyrSPI::transfer(void *buf, size_t len, const struct spi_config *config) { int ret; - const struct spi_buf tx_buf = {.buf = buf, .len = count}; + + const struct spi_buf tx_buf = {.buf = buf, .len = len}; const struct spi_buf_set tx_buf_set = { .buffers = &tx_buf, .count = 1, }; - uint8_t rx[count]; - const struct spi_buf rx_buf = {.buf = &rx, .len = count}; + const struct spi_buf rx_buf = {.buf = buf, .len = len}; const struct spi_buf_set rx_buf_set = { .buffers = &rx_buf, .count = 1, }; - spi_transceive(spi_dev, &config, &tx_buf_set, &rx_buf_set); - memcpy(buf, rx, count); + return spi_transceive(spi_dev, config, &tx_buf_set, &rx_buf_set); } void arduino::ZephyrSPI::usingInterrupt(int interruptNumber) { @@ -80,21 +56,31 @@ void arduino::ZephyrSPI::usingInterrupt(int interruptNumber) { void arduino::ZephyrSPI::notUsingInterrupt(int interruptNumber) { } -#ifndef SPI_MIN_CLOCK_FEQUENCY -#define SPI_MIN_CLOCK_FEQUENCY 1000000 -#endif - void arduino::ZephyrSPI::beginTransaction(SPISettings settings) { - memset(&config, 0, sizeof(config)); - memset(&config16, 0, sizeof(config16)); - config.frequency = settings.getClockFreq() > SPI_MIN_CLOCK_FEQUENCY ? settings.getClockFreq() : - SPI_MIN_CLOCK_FEQUENCY; - config16.frequency = config.frequency; + uint32_t mode = 0; + + // Set bus mode + switch (settings.getBusMode()) { + case SPI_CONTROLLER: + break; + case SPI_PERIPHERAL: + mode |= SPI_OP_MODE_SLAVE; + break; + } - auto mode = SPI_MODE_CPOL | SPI_MODE_CPHA; + // Set data format + switch (settings.getBitOrder()) { + case LSBFIRST: + mode |= SPI_TRANSFER_LSB; + break; + case MSBFIRST: + mode |= SPI_TRANSFER_MSB; + break; + } + + // Set data mode switch (settings.getDataMode()) { case SPI_MODE0: - mode = 0; break; case SPI_MODE1: mode = SPI_MODE_CPHA; @@ -106,12 +92,16 @@ void arduino::ZephyrSPI::beginTransaction(SPISettings settings) { mode = SPI_MODE_CPOL | SPI_MODE_CPHA; break; } - config.operation = SPI_WORD_SET(8) | - (settings.getBitOrder() == MSBFIRST ? SPI_TRANSFER_MSB : SPI_TRANSFER_LSB) | - mode; - config16.operation = - SPI_WORD_SET(16) | - (settings.getBitOrder() == MSBFIRST ? SPI_TRANSFER_MSB : SPI_TRANSFER_LSB) | mode; + + // Set SPI configuration structure for 8-bit transfers + memset(&config, 0, sizeof(struct spi_config)); + config.operation = mode | SPI_WORD_SET(8); + config.frequency = max(SPI_MIN_CLOCK_FEQUENCY, 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_FEQUENCY, settings.getClockFreq()); } void arduino::ZephyrSPI::endTransaction(void) { @@ -125,8 +115,6 @@ void arduino::ZephyrSPI::detachInterrupt() { } void arduino::ZephyrSPI::begin() { - beginTransaction(SPISettings()); - endTransaction(); } void arduino::ZephyrSPI::end() { diff --git a/libraries/SPI/SPI.h b/libraries/SPI/SPI.h index 95c41ce25..1e3f369db 100644 --- a/libraries/SPI/SPI.h +++ b/libraries/SPI/SPI.h @@ -22,6 +22,14 @@ #define SPE 6 #define SPIE 7 +#define SPI_HAS_PERIPHERAL_MODE (1) + +// TODO: +// This depends on the clock settings, can't be used for all boards. +#ifndef SPI_MIN_CLOCK_FEQUENCY +#define SPI_MIN_CLOCK_FEQUENCY 1000000 +#endif + /* Count the number of GPIOs for limit of number of interrupts */ #define INTERRUPT_HELPER(n, p, i) 1 #define INTERRUPT_COUNT \ @@ -50,6 +58,9 @@ class ZephyrSPI : public HardwareSPI { virtual void begin(); virtual void end(); +private: + int transfer(void *buf, size_t len, const struct spi_config *config); + protected: const struct device *spi_dev; struct spi_config config; From 3a1aef76e0f0fe784f01e2c4aeb3bc37ce2cd56c Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 11 Nov 2025 16:43:05 +0100 Subject: [PATCH 10/15] spi: fix data mode settings --- libraries/SPI/SPI.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/SPI/SPI.cpp b/libraries/SPI/SPI.cpp index 057b75d66..8cbf4af04 100644 --- a/libraries/SPI/SPI.cpp +++ b/libraries/SPI/SPI.cpp @@ -83,13 +83,13 @@ void arduino::ZephyrSPI::beginTransaction(SPISettings settings) { case SPI_MODE0: break; case SPI_MODE1: - mode = SPI_MODE_CPHA; + mode |= SPI_MODE_CPHA; break; case SPI_MODE2: - mode = SPI_MODE_CPOL; + mode |= SPI_MODE_CPOL; break; case SPI_MODE3: - mode = SPI_MODE_CPOL | SPI_MODE_CPHA; + mode |= SPI_MODE_CPOL | SPI_MODE_CPHA; break; } From 3f29a4195aa18cce3310f6bea8fa7eb7a1fadf9d Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 12 Nov 2025 08:29:54 +0100 Subject: [PATCH 11/15] spi: fix typo --- libraries/SPI/SPI.cpp | 4 ++-- libraries/SPI/SPI.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/SPI/SPI.cpp b/libraries/SPI/SPI.cpp index 8cbf4af04..1a0b39115 100644 --- a/libraries/SPI/SPI.cpp +++ b/libraries/SPI/SPI.cpp @@ -96,12 +96,12 @@ void arduino::ZephyrSPI::beginTransaction(SPISettings settings) { // Set SPI configuration structure for 8-bit transfers memset(&config, 0, sizeof(struct spi_config)); config.operation = mode | SPI_WORD_SET(8); - config.frequency = max(SPI_MIN_CLOCK_FEQUENCY, settings.getClockFreq()); + 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_FEQUENCY, settings.getClockFreq()); + 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 1e3f369db..2a25a8bf5 100644 --- a/libraries/SPI/SPI.h +++ b/libraries/SPI/SPI.h @@ -26,8 +26,8 @@ // TODO: // This depends on the clock settings, can't be used for all boards. -#ifndef SPI_MIN_CLOCK_FEQUENCY -#define SPI_MIN_CLOCK_FEQUENCY 1000000 +#ifndef SPI_MIN_CLOCK_FREQUENCY +#define SPI_MIN_CLOCK_FREQUENCY 1000000 #endif /* Count the number of GPIOs for limit of number of interrupts */ From 2ce93146338e7a0d2aaa01643163c320102fd202 Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Mon, 15 Dec 2025 18:44:15 +0100 Subject: [PATCH 12/15] warning cleanup: mark unused parameters with ARG_UNUSED macro Use the ARG_UNUSED macro provided by Zephyr to mark function parameters as intentionally unused to prevent compiler warnings. Signed-off-by: Luca Burelli --- libraries/Wire/Wire.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/libraries/Wire/Wire.cpp b/libraries/Wire/Wire.cpp index 18ec6140c..dd6d91554 100644 --- a/libraries/Wire/Wire.cpp +++ b/libraries/Wire/Wire.cpp @@ -100,6 +100,8 @@ uint8_t arduino::ZephyrI2C::endTransmission(bool stopBit) { size_t max = ring_buf_capacity_get(&txRingBuffer.rb); size_t len = ring_buf_get_claim(&txRingBuffer.rb, &buf, max); + ARG_UNUSED(stopBit); + ret = i2c_write(i2c_dev, buf, len, _address); // Must be called even if 0 bytes claimed. @@ -115,8 +117,11 @@ uint8_t arduino::ZephyrI2C::endTransmission(void) { size_t arduino::ZephyrI2C::requestFrom(uint8_t address, size_t len_in, bool stopBit) { int ret = -EIO; uint8_t *buf = NULL; - size_t len = ring_buf_put_claim(&rxRingBuffer.rb, &buf, len_in); + size_t len; + + ARG_UNUSED(stopBit); + len = ring_buf_put_claim(&rxRingBuffer.rb, &buf, len_in); if (len && buf) { ret = i2c_read(i2c_dev, buf, len, address); } @@ -171,6 +176,8 @@ void arduino::ZephyrI2C::onRequest(voidFuncPtr cb) { } int arduino::ZephyrI2C::writeRequestedCallback(struct i2c_target_config *config) { + ARG_UNUSED(config); + // Reset the buffer on write requests. ring_buf_reset(&rxRingBuffer.rb); return 0; @@ -180,6 +187,8 @@ int arduino::ZephyrI2C::writeReceivedCallback(struct i2c_target_config *config, size_t len = ring_buf_size_get(&rxRingBuffer.rb); size_t max = ring_buf_capacity_get(&rxRingBuffer.rb); + ARG_UNUSED(config); + // If the buffer is about to overflow, invoke the callback // with the current length. if (onReceiveCb && ((len + 1) > max)) { @@ -201,6 +210,8 @@ int arduino::ZephyrI2C::readRequestedCallback(struct i2c_target_config *config, } int arduino::ZephyrI2C::readProcessedCallback(struct i2c_target_config *config, uint8_t *val) { + ARG_UNUSED(config); + *val = 0xFF; ring_buf_get(&txRingBuffer.rb, val, 1); // Returning a negative value here is not handled gracefully and @@ -209,6 +220,8 @@ int arduino::ZephyrI2C::readProcessedCallback(struct i2c_target_config *config, } int arduino::ZephyrI2C::stopCallback(struct i2c_target_config *config) { + ARG_UNUSED(config); + // If the RX buffer is not empty invoke the callback with the // remaining data length. if (onReceiveCb) { From 20f7b9dd1d5261d658aac0807893e9fe9a0411ef Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Mon, 15 Dec 2025 18:49:05 +0100 Subject: [PATCH 13/15] warning cleanup: reorder constructor initialization list Constructors should initialize members in the order they are declared in the class definition. Signed-off-by: Luca Burelli --- libraries/Wire/Wire.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/Wire/Wire.cpp b/libraries/Wire/Wire.cpp index dd6d91554..696813b89 100644 --- a/libraries/Wire/Wire.cpp +++ b/libraries/Wire/Wire.cpp @@ -48,7 +48,7 @@ static struct i2c_target_callbacks target_callbacks = { .stop = i2c_target_stop_cb, }; -arduino::ZephyrI2C::ZephyrI2C(const struct device *i2c) : i2c_dev(i2c), i2c_cfg({0}) { +arduino::ZephyrI2C::ZephyrI2C(const struct device *i2c) : i2c_cfg({0}), i2c_dev(i2c) { ring_buf_init(&txRingBuffer.rb, sizeof(txRingBuffer.buffer), txRingBuffer.buffer); ring_buf_init(&rxRingBuffer.rb, sizeof(rxRingBuffer.buffer), rxRingBuffer.buffer); } From da11f26558e56d6d5c32fc6ee15448e1b481b409 Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Mon, 15 Dec 2025 18:58:35 +0100 Subject: [PATCH 14/15] warning cleanup: misc fixes - Arduino_LED_Matrix: fix packed attribute placement, add missing dependency - Camera: fix pixel format check (formats are uint32_t, not pointers) - Ethernet: fix float division literals - SocketWrapper: hide deprecated warnings, fix signed/unsigned compare - Wire: hide pedantic 'invalid offsetof' warning --- libraries/Wire/Wire.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/Wire/Wire.cpp b/libraries/Wire/Wire.cpp index 696813b89..c7d97587f 100644 --- a/libraries/Wire/Wire.cpp +++ b/libraries/Wire/Wire.cpp @@ -10,8 +10,11 @@ // Helper function to get ZephyrI2C instance from config pointer. static arduino::ZephyrI2C *getInstance(struct i2c_target_config *config) { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Winvalid-offsetof" return reinterpret_cast(reinterpret_cast(config) - offsetof(arduino::ZephyrI2C, i2c_cfg)); +#pragma GCC diagnostic pop } static int i2c_target_stop_cb(struct i2c_target_config *config) { From ba76a67420e70a6d8f4535f3f17460b08079bb7c Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Wed, 10 Dec 2025 15:05:27 +0100 Subject: [PATCH 15/15] 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 1a0b39115..33ddd319a 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()) {