Skip to content

SPI.transfer(buffer, size) definition incompatible with other cores #5787

Closed
@s-light

Description

@s-light

challenge

i try to use the ulrichstern/Tlc59711 LED-Driver library to use with an ESP32 Dev Module.

this currently results in this compilation error:

/home/stefan/mydata/arduino_sketchbook/libraries/ulrichstern_Tlc59711/Tlc59711.cpp: In member function 'void Tlc59711::xferSpi()':
/home/stefan/mydata/arduino_sketchbook/libraries/ulrichstern_Tlc59711/Tlc59711.cpp:148:39: error: no matching function for call to 'SPIClass::transfer(uint16_t*&, int)'
       SPI.transfer(buffer2, bufferSz*2);
                                       ^
In file included from /home/stefan/mydata/arduino_sketchbook/libraries/ulrichstern_Tlc59711/Tlc59711.cpp:11:
/home/stefan/.arduino15/packages/esp32/hardware/esp32/2.0.0/libraries/SPI/src/SPI.h:70:10: note: candidate: 'void SPIClass::transfer(uint8_t*, uint32_t)'
     void transfer(uint8_t * data, uint32_t size);
          ^~~~~~~~
/home/stefan/.arduino15/packages/esp32/hardware/esp32/2.0.0/libraries/SPI/src/SPI.h:70:10: note:   no known conversion for argument 1 from 'uint16_t*' {aka 'short unsigned int*'} to 'uint8_t*' {aka 'unsigned char*'}
/home/stefan/.arduino15/packages/esp32/hardware/esp32/2.0.0/libraries/SPI/src/SPI.h:71:13: note: candidate: 'uint8_t SPIClass::transfer(uint8_t)'
     uint8_t transfer(uint8_t data);
             ^~~~~~~~
/home/stefan/.arduino15/packages/esp32/hardware/esp32/2.0.0/libraries/SPI/src/SPI.h:71:13: note:   candidate expects 1 argument, 2 provided

after some research i found that in the ESP32 core the definition of SPI.transfer(buffer, size) differs to other cores.

Minimal Example

with this the error can be reproduces if the board is a ESP32 Dev Kit
with AVR or SAMD it is compiling fine.

#include <SPI.h>

void setup() {
    SPI.begin();
    SPI.beginTransaction(SPISettings(2*1000*1000, MSBFIRST, SPI_MODE0));

    uint16_t *buffer;
    const uint16_t bufferSz = 10;
    buffer = reinterpret_cast<uint16_t*>(malloc(2*bufferSz));

    SPI.transfer(buffer, bufferSz*2);
}

void loop() {
}

down the rabbit hole

currently the definition is:
libraries/SPI/src/SPI.h#70

void transfer(uint8_t * data, uint32_t size);

libraries/SPI/src/SPI.cpp#229

void SPIClass::transfer(uint8_t * data, uint32_t size) 
{ 
	transferBytes(data, data, size); 
}

this was added in #2136.

in the avr core its defined as

inline static void transfer(void *buf, size_t count) {

and in the samd core as

void transfer(void *buf, size_t count);

solution

so to be cross-platform compatible it is needed to change the parameters to the same types - void *data, size_t count

i don't know yet what is need to get the called transferBytes function to work with this.
i tested with this implementation:

void SPIClass::transfer(void * data, size_t size)
{
    transferBytes(
        reinterpret_cast<uint8_t*>(data),
        reinterpret_cast<uint8_t*>(data),
        size);
}

its inspired by the other implementations - and it seems to work.
but i am not 100% sure if there are other side effects - so please review!

Hardware

Board: ESP32 Dev Module
Core Installation version: 2.0.0
IDE name: Arduino IDE
Flash Frequency: 80Mhz
PSRAM enabled: no
Upload Speed: 921600
Computer OS: Kubuntu 20.04

Metadata

Metadata

Assignees

Type

No type

Projects

Status

Done

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions