From fd83628c4985dec2d81f711826f3eb9c927152ef Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Tue, 17 Jun 2025 12:30:09 +1000 Subject: [PATCH] [spi] Cater for non-word-aligned buffers on esp8266 (#9108) --- esphome/components/spi/spi_arduino.cpp | 31 ++++++++++++++++++-------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/esphome/components/spi/spi_arduino.cpp b/esphome/components/spi/spi_arduino.cpp index f7fe523a33..432f7cf2cd 100644 --- a/esphome/components/spi/spi_arduino.cpp +++ b/esphome/components/spi/spi_arduino.cpp @@ -3,7 +3,6 @@ namespace esphome { namespace spi { - #ifdef USE_ARDUINO static const char *const TAG = "spi-esp-arduino"; @@ -38,17 +37,31 @@ class SPIDelegateHw : public SPIDelegate { void write16(uint16_t data) override { this->channel_->transfer16(data); } -#ifdef USE_RP2040 void write_array(const uint8_t *ptr, size_t length) override { - // avoid overwriting the supplied buffer - uint8_t *rxbuf = new uint8_t[length]; // NOLINT(cppcoreguidelines-owning-memory) - memcpy(rxbuf, ptr, length); - this->channel_->transfer((void *) rxbuf, length); - delete[] rxbuf; // NOLINT(cppcoreguidelines-owning-memory) - } + if (length == 1) { + this->channel_->transfer(*ptr); + return; + } +#ifdef USE_RP2040 + // avoid overwriting the supplied buffer. Use vector for automatic deallocation + auto rxbuf = std::vector(length); + memcpy(rxbuf.data(), ptr, length); + this->channel_->transfer((void *) rxbuf.data(), length); +#elif defined(USE_ESP8266) + // ESP8266 SPI library requires the pointer to be word aligned, but the data may not be + // so we need to copy the data to a temporary buffer + if (reinterpret_cast(ptr) & 0x3) { + ESP_LOGVV(TAG, "SPI write buffer not word aligned, copying to temporary buffer"); + auto txbuf = std::vector(length); + memcpy(txbuf.data(), ptr, length); + this->channel_->writeBytes(txbuf.data(), length); + } else { + this->channel_->writeBytes(ptr, length); + } #else - void write_array(const uint8_t *ptr, size_t length) override { this->channel_->writeBytes(ptr, length); } + this->channel_->writeBytes(ptr, length); #endif + } void read_array(uint8_t *ptr, size_t length) override { this->channel_->transfer(ptr, length); }