10000 Multiple SPIClass objects cause failure in version 3.0.2 · Issue #9939 · espressif/arduino-esp32 · GitHub
[go: up one dir, main page]

Skip to content
Multiple SPIClass objects cause failure in version 3.0.2 #9939
Closed
@oxothnk423

Description

@oxothnk423

Board

custom PCB

Device Description

ESP32-S3 FN8 with three SPI devices:
ICM 20948 9-axis IMU
MS5611-01BA03 barometric pressure sensor
192x64 monochrome LCD

Hardware Configuration

ESP32-S3 FN8 with three SPI devices connected to default VSPI (FSPI) pins (MOSI, MISO, CLK) and separate chip select pins.

Version

latest master (checkout manually)

IDE Name

Arduino IDE 2.3.2

Operating System

Windows 10

Flash frequency

QIO 80Mhz

PSRAM enabled

no

Upload speed

921600

Description

In ESP32 version 2.0.14, I was able to initialize each SPI device separately with its own SPIClass, even though they're all pointing to the same bus (VSPI in this case). This allows for unique settings (such as chip select pin) per spi device / class. In setup(), each device's class would then need a call to SPIClass->begin().
In version 3.0.2, it seems repeat calls to spi->begin() for the same spi bus creates a conflict or failure, such that the code hangs (with no error thrown) when performing a call to spi->transfer().

A simplified version of the code is below, which works on 2.0.14 and DOES NOT work on 3.0.2. The specific conflict I believe is the second call to spi->begin for the second device. If this line (imu_vspi->begin(...);) is commented out, the code compiles and runs without hanging (even though the SPI communication isn't as expected since the second device is now not set up properly).

There are ways to work around this if I was only using exclusively my own code, but some popular libraries (for example I'm using u8g2 for the LCD) internally handle their own SPI device setup. This makes it nearly impossible to avoid repeat calls to spi->begin on the same bus. (in other words, I can set up a single SPIClass to manage my other devices, or I can initialize the u8g2 library, but not both).

Is there a better way to approach multiple SPI devices on the same bus? I'd love to learn I'm just doing something wrong... I'm happy to take advice on alternative approaches. But this approach worked great in V2.x, so I'm surprised to see it failing here in v3.x when there were no listed breaking changes in the SPI API's (as far as I saw).

Sketch

#include <SPI.h>

#define SPI_SS_IMU       10
#define SPI_MOSI         11
#define SPI_CLK          12
#define SPI_MISO         13  
#define SPI_SS_BARO      18

#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
#define VSPI FSPI
#endif

static const int spiClk = 1000000;  // 1 MHz

//uninitialised pointers to SPI objects
SPIClass * baro_vspi = NULL;
SPIClass * imu_vspi = NULL;

void setup() {
  delay(1000);
  Serial.begin(115200);
  delay(1000);
  Serial.println("Starting Setup");
  
  baro_vspi = new SPIClass(VSPI);
  baro_vspi->begin(SPI_CLK, SPI_MISO, SPI_MOSI, SPI_SS_BARO);
  pinMode(baro_vspi->pinSS(), OUTPUT);
  digitalWrite(baro_vspi->pinSS(), HIGH);

  imu_vspi = new SPIClass(VSPI);
  imu_vspi->begin(SPI_CLK, SPI_MISO, SPI_MOSI, SPI_SS_IMU);   // comment this line out to make it "work"
  pinMode(imu_vspi->pinSS(), OUTPUT);
  digitalWrite(imu_vspi->pinSS(), HIGH);
}

void loop() {
  spi_Command(baro_vspi, 0b01010101);  // junk data to illustrate usage
  delay(100);
  spi_Command(imu_vspi, 0b01010101);  // junk data to illustrate usage
  delay(100);
}

void spi_Command(SPIClass *spi, byte data) {
  
  spi->beginTransaction(SPISettings(spiClk, MSBFIRST, SPI_MODE0));    
  digitalWrite(spi->pinSS(), LOW);                                    
  spi->transfer(data);                // code hangs here, doesn't return
  digitalWrite(spi->pinSS(), HIGH);                                    
  spi->endTransaction();                                                
}

Debug Message

no visible errors.  As mentioned above, the code just hangs on the third to last line (it never returns from spi->transfer).

Other Steps to Reproduce

As mentioned, this has worked correctly on 2.0.14. I am able to initialize 3 separate SPIClasses, all pointing to VSPI, and each with their own spi->begin() call, and also initialize a fourth u8g2 library spi object.... and SPI transfers worked flawlessly among all of them.

Now in v3.0.2, I only seem to be able to make a single spi->begin call, which thus enables only one SPIClass, not multiple.

I have checked existing issues, online documentation and the Troubleshooting Guide

  • I confirm I have checked existing issues, online documentation and Troubleshooting guide.

Metadata

Metadata

Assignees

Labels

Area: LibrariesIssue is related to Library support.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions

    0