The ESP32S3 SPI slave cannot fully receive data

393877719
Posts: 10
Joined: Wed Jun 13, 2018 5:52 am

The ESP32S3 SPI slave cannot fully receive data

Postby 393877719 » Thu Mar 07, 2024 3:30 am

Hi,
I have a project that needs to use 2 SPI peripherals of ESP32S3, one for SPI host and one for SPI slave. It is used to connect an SPI device that has both an SPI host and an SPI slave.
The SPI host of the ESP32S3 connects to the SPI slave of the SPI device, and the SPI slave of the ESP32S3 connects to the SPI host of the SPI device, as shown in the following figure.
SPI.jpg
SPI.jpg (27.86 KiB) Viewed 520 times
The communication between ESP32S3 and SPI device is initiated by SPI host of ESP32S3, after ESP32S3 sends a 6-byte data frame through SPI host port, SPI device will respond to the corresponding data through SPI slave port of ESP32S3, Each response will be divided into multiple data frames for transmission, each frame is 6-bytes. And the frame interval is about 5us.
I used the spi_slave_transmit() and spi_slave_queue_trans() functions respectively, but all data frames could not be received normally. Therefore, I tested with the following code and found that the SPI frame interval was too short and the ESP32S3 could not receive all in time if i used the spi_device_queue_trans() functions.
queue.png
queue.png (158.82 KiB) Viewed 520 times
but, if i used the the spi_device_transmit() , the ESP32S3 can receive all in time, but the frame interval is too long, and this is not i wanted.
normal_trans.png
normal_trans.png (126.65 KiB) Viewed 520 times
Do you have a better way to solve the ESP32S3 continuous receiving frame interval of less than 5us, hope to get your reply, thank you!

Code: Select all

#include <stdio.h>
#include "driver/spi_master.h"
#include "driver/spi_slave.h"
#include "esp_heap_caps.h"

#define GPIO_MOSI_S 19
#define GPIO_SCLK_S 20
#define GPIO_CS_S 21

#define GPIO_MOSI_M 35
#define GPIO_SCLK_M 34
#define GPIO_CS_M 33

esp_err_t ret;
spi_device_handle_t Master_handle;

void SPI_RX_task(void *param)
{
    spi_slave_transaction_t t[6];
    uint8_t *recvbuf[6];

    for (uint8_t i = 0; i < 6; i++)
    {
        recvbuf[i] = heap_caps_malloc(6, MALLOC_CAP_DMA);
        t[i].length = 6 * 8;
        t[i].tx_buffer = NULL;
        t[i].rx_buffer = recvbuf[i];
    }
    spi_slave_transaction_t *ret_trans;
    while (1)
    {
        for (uint8_t i = 0; i < 6; i++)
        {
            ret = spi_slave_queue_trans(SPI2_HOST, &t[i], portMAX_DELAY);
            assert(ret == ESP_OK);
        }
        for (uint8_t i = 0; i < 6; i++)
        {
            ret = spi_slave_get_trans_result(SPI2_HOST, &ret_trans, portMAX_DELAY);
            assert(ret == ESP_OK);
            for (uint8_t j = 0; j < 6; j++)
            {
                printf("%02X ", recvbuf[i][j]);
            }
            printf("\n");
        }
    }
    vTaskDelete(NULL);
}

void ESP_SPI_Slave_Init(void)
{
    // Configuration for the SPI bus
    spi_bus_config_t buscfg = {
        .mosi_io_num = GPIO_MOSI_S,
        .miso_io_num = -1,
        .sclk_io_num = GPIO_SCLK_S,
        .quadwp_io_num = -1,
        .quadhd_io_num = -1,
    };

    // Configuration for the SPI slave interface
    spi_slave_interface_config_t slvcfg = {
        .mode = 0,
        .spics_io_num = GPIO_CS_S,
        .queue_size = 6,
        .flags = 0,
    };

    // Initialize SPI slave interface
    ret = spi_slave_initialize(SPI2_HOST, &buscfg, &slvcfg, SPI_DMA_CH_AUTO);
    assert(ret == ESP_OK);
}
void ESP_SPI_Master_Init(void)
{
    spi_bus_config_t busconfig = {
        .mosi_io_num = GPIO_MOSI_M,
        .miso_io_num = -1,
        .sclk_io_num = GPIO_SCLK_M,
        .quadhd_io_num = -1,
        .quadwp_io_num = -1,
    };
    ret = spi_bus_initialize(SPI3_HOST, &busconfig, SPI_DMA_CH_AUTO);
    ESP_ERROR_CHECK(ret);
    spi_device_interface_config_t mstconfig = {
        .spics_io_num = GPIO_CS_M,
        .clock_speed_hz = 2000000,
        .mode = 3,
        .queue_size = 6,
        .cs_ena_pretrans = 1,
        .cs_ena_posttrans = 1,
    };
    ret = spi_bus_add_device(SPI3_HOST, &mstconfig, &Master_handle);
    ESP_ERROR_CHECK(ret);
}

void app_main(void)
{
    uint8_t *sendbuf = heap_caps_malloc(6, MALLOC_CAP_DMA);
    for (uint8_t i = 0; i < 6; i++)
    {
        sendbuf[i] = i + 1;
    }
    ESP_SPI_Slave_Init();
    ESP_SPI_Master_Init();
    xTaskCreate(SPI_RX_task, "SPI_RX_task", 1024 * 3, NULL, 1, NULL);
    spi_transaction_t t[6];
    for (uint8_t i = 0; i < 6; i++)
    {
        t[i].length = 6 * 8;
        t[i].rxlength = 0;
        t[i].tx_buffer = sendbuf;
        t[i].rx_buffer = NULL;
        t[i].flags = 0;
    }
    spi_transaction_t *ret_trans;
    while (1)
    {
        // 1. use spi_device_queue_trans(), Minimum frame interval = 21.04us
        // for (uint8_t i = 0; i < 6; i++)
        // {
        //     ret = spi_device_queue_trans(Master_handle, &t[i], portMAX_DELAY);
        // }
        // for (uint8_t i = 0; i < 6; i++)
        // {
        //     ret = spi_device_get_trans_result(Master_handle, &ret_trans, portMAX_DELAY);
        // }
        // 2. use spi_device_transmit(), Minimum frame interval = 58.8us
        for(uint8_t i = 0; i < 6; i++)
        {
            spi_device_transmit(Master_handle, &t[i]);
        }
        vTaskDelay(pdMS_TO_TICKS(3000));
    }
    heap_caps_free(sendbuf);
    vTaskDelete(NULL);
}

MicroController
Posts: 1385
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: The ESP32S3 SPI slave cannot fully receive data

Postby MicroController » Thu Mar 07, 2024 12:03 pm

Do you have a better way to solve the ESP32S3 continuous receiving frame interval of less than 5us, hope to get your reply, thank you!
If you haven't already, you must at least get rid of printf's or other logging between the transactions.

393877719
Posts: 10
Joined: Wed Jun 13, 2018 5:52 am

Re: The ESP32S3 SPI slave cannot fully receive data

Postby 393877719 » Thu Mar 07, 2024 12:54 pm

MicroController wrote:
Thu Mar 07, 2024 12:03 pm
If you haven't already, you must at least get rid of printf's or other logging between the transactions.
As you can see, I set the SPI queue send interval to 3-seconds in the test code, and I think that even if printf is used in the receive task, the result will not be affected.
by the way, during the test, I directly connected SPI2 and SPI3 through wires, that is, GPIO19 connected GPIO35, GPIO20 connected GPIO34,GPIO21 connected GPIO33.

MicroController
Posts: 1385
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: The ESP32S3 SPI slave cannot fully receive data

Postby MicroController » Thu Mar 07, 2024 5:08 pm

Yes, I failed to see that you enqueue all transactions first.

Did you see https://docs.espressif.com/projects/esp ... n-interval ?

Who is online

Users browsing this forum: No registered users and 86 guests