SPI2 and SPI3 in parallel

Suxsem
Posts: 3
Joined: Mon Jun 26, 2023 5:47 pm

SPI2 and SPI3 in parallel

Postby Suxsem » Sun Aug 13, 2023 9:25 am

Hi all,

I'm trying to achieve very high speed in controlling a 4-PIN (SPI) LED strip with an ESP32-S3.

The strip only receives messages from SPI, it never replies, so it only has 2 pins for the SPI: MOSI and CLK.

In order to halve the communication time between the ESP32-S3 and the strip i decided to split the strip in two halves and drive the two halves in parallel with SPI2 and SPI3 buses.

I can successfully initialize both buses and talk with each halve of the strip independently, but I'm having hard times sending the commands to the two buses concurrently.

Please keep in mind that I'm using DMA so I'm expecting the two SPI hosts to be able to work independently.

My initial idea was to use something like

Code: Select all

spi_device_polling_start(spi_A, &t_A, portMAX_DELAY);
spi_device_polling_start(spi_B, &t_B, portMAX_DELAY);
spi_device_polling_end(spi_A, portMAX_DELAY);
spi_device_polling_end(spi_B, portMAX_DELAY);
but it seems that spi_device_polling_start cannot be invoked if a previous polling transaction is still in progress, despite the two device handlers (spi_A and spi_B) referring to different SPI hosts.

Does the ESP32-S3 hardware (SPI hosts, DMA channels, ...) allows concurrent SPI transfers? Is this some kind of software limitation of the ESP-IDF framework? Or, more probably, am I doing something wrong? :D

Thank you!

ESP_Sprite
Posts: 9739
Joined: Thu Nov 26, 2015 4:08 am

Re: SPI2 and SPI3 in parallel

Postby ESP_Sprite » Mon Aug 14, 2023 2:53 am

Can you post your entire code?

Suxsem
Posts: 3
Joined: Mon Jun 26, 2023 5:47 pm

Re: SPI2 and SPI3 in parallel

Postby Suxsem » Mon Aug 14, 2023 9:07 am

Oooops....it actually worked!

The problem was that the spi_transaction_t variable was a local one and the spi_device_polling_end function was called in a different function than spi_device_polling_start, so it was removed from the stack but somehow the driver needs it to store results of the transaction (it make sense, but I thought that for tx-only transmissions the variable would only be read when transaction started, maybe a note in the documentation would clarify this).

So basically the broken code was something like this:

Code: Select all

void loop() {
    start_A();
    start_B();
    end_A();
    end_B();
}

void start_A() {
    spi_transaction_t t = {
        .length = 1024,
        .tx_buffer = buffer_A
    };
    spi_device_polling_start(spi_A, &t, portMAX_DELAY);
    //ops...t is removed from the stack on return...
}

void start_B() {
    spi_transaction_t t = {
        .length = 1024,
        .tx_buffer = buffer_B
    };
    spi_device_polling_start(spi_B, &t, portMAX_DELAY);
    //ops...t is removed from the stack on return...
}

void end_A() {
    spi_device_polling_end(spi_A, portMAX_DELAY);
}

void end_B() {
    spi_device_polling_end(spi_B, portMAX_DELAY);
}
and it's fixed like this:

Code: Select all

spi_transaction_t *t_A;
spi_transaction_t *t_B;

void setup() {
    t_A = (spi_transaction_t*)malloc(sizeof(spi_transaction_t));
    t_B = (spi_transaction_t*)malloc(sizeof(spi_transaction_t));
}

void loop() {
    start_A();
    start_B();
    end_A();
    end_B();
}

void start_A() {
    memset(t_A, 0, sizeof(*t_A));
    t_A->length = 1024;
    t_A->tx_buffer = buffer_A;
    spi_device_polling_start(spi_A, t_A, portMAX_DELAY);
}

void start_B() {
    memset(t_B, 0, sizeof(*t_B));
    t_B->length = 1024;
    t_B->tx_buffer = buffer_B;
    spi_device_polling_start(spi_B, t_B, portMAX_DELAY);

}

void end_A() {
    spi_device_polling_end(spi_A, portMAX_DELAY);
}

void end_B() {
    spi_device_polling_end(spi_B, portMAX_DELAY);
}
sorry for the useless thread!

ESP_Sprite
Posts: 9739
Joined: Thu Nov 26, 2015 4:08 am

Re: SPI2 and SPI3 in parallel

Postby ESP_Sprite » Tue Aug 15, 2023 1:54 am

No problem, glad you resolved it!

Who is online

Users browsing this forum: Majestic-12 [Bot], snutw_ and 69 guests