espressif / esp-idf

Espressif IoT Development Framework. Official development framework for Espressif SoCs.
Apache License 2.0
13.29k stars 7.2k forks source link

SPI lost packets (IDFGH-1700) #3939

Open zavovi opened 5 years ago

zavovi commented 5 years ago

Hello, please, I am working on SPI slave node with ESP32 and esp-idf and I have one issue. I am transmitting blocks with 64 bytes and when I transmit all 64 bytes and I want transmit next and next, then some blocks are missing there. I tried check the line on scope and I see all data, but not received in ESP32 module. Please, could you help me or check, if is it the issue in esp-idf?

This is my communication task:

#define TCS_COMM_RX_TX_SIZE         64

static void tcs_communication_rx_tx_task(void *pvParameter)
{
    tcs_err_t err;
    uint8_t * rx_data;
    uint8_t * tx_data;
    uint32_t tx_size = 0;

    comm_ctx.events = xEventGroupCreate();

    ESP_LOGI(TAG, "Starting RX/TX task...");

    if(comm_ctx.type == COMM_TYPE_UART)
    {
        /* Initialize UART */
        err = tcs_uart_init();
    }
    else if(comm_ctx.type == COMM_TYPE_SPI)
    {
        /* Initialize SPI */
        err = tcs_spi_init();
    }
    else
    {
        ESP_LOGE(TAG, "Bad communication type!\n");
        err = TCS_ERR_BADPARAM;
    }

    if(TCS_FAILED(err))
        goto ERROR;

    /* Prepare buffers */
    tcs_buffer_prepare(&comm_ctx.rx, TCS_COMM_RX_TX_SIZE);  //TCS_COMM_RX_TX_SIZE = 64
    tcs_buffer_prepare(&comm_ctx.tx, TCS_COMM_RX_TX_SIZE);  //TCS_COMM_RX_TX_SIZE = 64

    /* Prepare RX buffer */
    rx_data = heap_caps_malloc(TCS_COMM_RX_TX_SIZE+1, MALLOC_CAP_DMA);
    if(rx_data == NULL)
    {
        ESP_LOGE(TAG, "Error in malloc receive buffer.\n");
        err = TCS_ERR_NOMEM;
        goto ERROR;
    }

    /* Prepare TX buffer */
    tx_data = heap_caps_malloc(TCS_COMM_RX_TX_SIZE+1, MALLOC_CAP_DMA);
    if(tx_data == NULL)
    {
        ESP_LOGE(TAG, "Error in malloc transmit buffer.\n");
        err = TCS_ERR_NOMEM;
        goto ERROR;
    }

    memset(rx_data, 0, TCS_COMM_RX_TX_SIZE+1);
    memset(tx_data, 0, TCS_COMM_RX_TX_SIZE+1);

    comm_ctx.initialized = true;

    while(1)
    {
        if(comm_ctx.type == COMM_TYPE_UART)
        {
            int received = uart_read_bytes(COMM_UART_NUM, rx_data, TCS_COMM_RX_TX_SIZE, 10 / portTICK_RATE_MS);
            if(received < 0)
            {
                ESP_LOGE(TAG, "UART read bytes failed!\n");
                err = TCS_ERR_COMM;
            }
            else
            {

                /* Wait for not locked */
                while(tcs_buffer_is_locked(&comm_ctx.rx));

                /* Lock buffer */
                tcs_buffer_lock(&comm_ctx.rx);

                tcs_buffer_add(&comm_ctx.rx, rx_data, received, true);

                /* Unlock buffer */
                tcs_buffer_unlock(&comm_ctx.rx);

                /* set event for receive task */
                xEventGroupSetBits(comm_ctx.events, COMM_EVENT_RX);
            }
        }
        else if(comm_ctx.type == COMM_TYPE_SPI)
        {
            spi_slave_transaction_t t;

            if(comm_ctx.spi_pending)
                continue;

            memset(&t, 0, sizeof(t));

            memset(rx_data, 0, TCS_COMM_RX_TX_SIZE+1);
            memset(tx_data, 0, TCS_COMM_RX_TX_SIZE+1);

            tx_size = 0;

            t.length = TCS_COMM_RX_TX_SIZE*8;
            t.rx_buffer = rx_data;

            t.trans_len = 0;
            t.tx_buffer = tx_data;

            /* Wait for not locked */
            while(tcs_buffer_is_locked(&comm_ctx.tx));

            /* Lock buffer */
            tcs_buffer_lock(&comm_ctx.tx);

            tx_size = tcs_buffer_get_used(&comm_ctx.tx);

            /* Copy TX data from context to transmit buffer */
            if(tx_size > 0)
            {
                printf("TX%d\n", tx_size);

                if(tx_size > TCS_COMM_RX_TX_SIZE-3)
                    tx_size = TCS_COMM_RX_TX_SIZE-3;

                memcpy(tx_data+3, comm_ctx.tx.buffer, tx_size);

                /* START byte */
                tx_data[0] = 0x88;
                /* TX len */
                tx_data[1] = TCS_LOBYTE(tx_size);
                tx_data[2] = TCS_HIBYTE(tx_size);

                /* Consume buffer */
                tcs_buffer_consume(&comm_ctx.tx, tx_size);

                ESP_LOG_BUFFER_HEX(TAG, tx_data, tx_size+3);

                t.trans_len = (tx_size+3)*8;
                t.tx_buffer = tx_data;

            }

            /* Unlock buffer */
            tcs_buffer_unlock(&comm_ctx.tx);

            comm_ctx.spi_pending = true;
            esp_err_t ret = spi_slave_transmit(COMM_SPI_HOST, &t,/* 100 / portTICK_RATE_MS*/portMAX_DELAY);
            if(ret == ESP_ERR_TIMEOUT)
            {
                printf("t");
                comm_ctx.spi_pending = false;
                /* Do nothing */
                continue;
            }
            else if(ret != ESP_OK)
            {
                comm_ctx.spi_pending = false;
                ESP_LOGE(TAG, "SPI RX/TX failed (0x%02x)!\n", ret);
                err = TCS_ERR_COMM;
            }
            else
            {
                /* Wait for not locked */
                while(tcs_buffer_is_locked(&comm_ctx.rx));

                /* Lock buffer */
                tcs_buffer_lock(&comm_ctx.rx);

                uint16_t rxlen = 0;
                if((t.trans_len/8) > 3 && rx_data[0] == 0x88)
                {
                    rxlen = TCS_UINT16(rx_data[1], rx_data[2]);

                    ESP_LOGW(TAG, "SPI RX - %d.", t.trans_len/8);
                    {
                        ESP_LOG_BUFFER_HEX(TAG, rx_data, t.trans_len/8);

                        ESP_LOGW(TAG, "SPI RX (%d).", rxlen);

                        tcs_buffer_add(&comm_ctx.rx, rx_data+3, rxlen, true);
                    }
                }

                /* Unlock buffer */
                tcs_buffer_unlock(&comm_ctx.rx);

                xEventGroupSetBits(comm_ctx.events, COMM_EVENT_RX);
            }
        }
    }

ERROR:
    vTaskDelay(1000 / portTICK_PERIOD_MS);
    esp_restart();
}

/* Called after a transaction is queued and ready for pickup by master. We use this to set the handshake line high. */
static void tcs_post_setup_cb(spi_slave_transaction_t *trans)
{
    WRITE_PERI_REG(GPIO_OUT_W1TS_REG, (1<<COMM_SPI_GPIO_HANDSHAKE));    //IO16
}

/* Called after transaction is sent/received. We use this to set the handshake line low. */
static void tcs_post_trans_cb(spi_slave_transaction_t *trans)
{
    WRITE_PERI_REG(GPIO_OUT_W1TC_REG, (1<<COMM_SPI_GPIO_HANDSHAKE));    //IO16
    comm_ctx.spi_pending = false;
}

static tcs_err_t tcs_spi_init(void)
{
    esp_err_t err;

    /* Configuration for the SPI bus */
    spi_bus_config_t buscfg=
    {
        .mosi_io_num = COMM_SPI_GPIO_MOSI,  //IO12
        .miso_io_num = COMM_SPI_GPIO_MISO,  //IO13
        .sclk_io_num = COMM_SPI_GPIO_SCLK   //IO15
    };

    /* Configuration for the SPI slave interface */
    spi_slave_interface_config_t slvcfg=
    {
        .mode = 0,
        .spics_io_num = COMM_SPI_GPIO_CS, //IO14
        .queue_size = 5,
        .flags = 0,
        .post_setup_cb = tcs_post_setup_cb,
        .post_trans_cb = tcs_post_trans_cb
    };

    /* Configuration for the handshake line */
    gpio_config_t io_conf=
    {
        .intr_type  = GPIO_INTR_DISABLE,
        .mode       = GPIO_MODE_OUTPUT,
        .pin_bit_mask = (1<<COMM_SPI_GPIO_HANDSHAKE)    //IO16
    };

    /* Configure handshake line as output */
    gpio_config(&io_conf);

    //Enable pull-ups on SPI lines so we don't detect rogue pulses when no master is connected.
    gpio_set_pull_mode(COMM_SPI_GPIO_MOSI, GPIO_PULLUP_ONLY);
    gpio_set_pull_mode(COMM_SPI_GPIO_SCLK, GPIO_PULLUP_ONLY);
    gpio_set_pull_mode(COMM_SPI_GPIO_CS, GPIO_PULLUP_ONLY);

    /* Initialize SPI slave interface */
    err = spi_slave_initialize(COMM_SPI_HOST, &buscfg, &slvcfg, 1); //COMM_SPI_HOST = HSPI_HOST
    if(err != ESP_OK)
    {
        ESP_LOGE(TAG, "Error in function spi_slave_initialize!\n");
        return TCS_ERR_COMM;
    }

    return TCS_OK;
}

The communication is controlled by master, which is waiting for interrupts from COMM_SPI_GPIO_HANDSHAKE. When the COMM_SPI_GPIO_HANDSHAKE is low -> It is ready to receive data, when it is high --> It is ready to send data.

Please, could you help me? Thank you very much!

zavovi commented 5 years ago

And the speed from master is 500Kb.

Alvin1Zhang commented 5 years ago

@zavovi Thanks for reporting the issue. Would you please help provide more details as suggested in the issue template? Information like elf, sdk configuration, backtrace, log outputs, commit ID, hardware and etc. would help us debug further. Thanks.

zavovi commented 5 years ago

Environment Development Kit: ESP32-DevKit Kit version (DevKit): v1 Module or chip used: ESP32-WROOM-32 IDF version (run git describe --tags to find it): v3.3-beta3-181-g70ecb7ec9 Build System: Make Compiler version (run xtensa-esp32-elf-gcc --version to find it): (crosstool-NG crosstool-ng-1.22.0-80-g6c4433a5) 5.2.0 Operating System: Windows Power Supply: USB

Make command: make flash ESPPORT=COM10 -j4 monitor

Note: This kit is connected to FRDM-K64 development kit for communication over SPI. It was tested on wire connection and on the my own board, where is connection between both MCUs on the board.

Problem Description

Expected Behavior: Receiving all SPI packets. Actual Behavior: Lost each second SPI packet.

I am attaching my ELF (bin) file, sdkconfig, logs and readme. I haven't got two ESP32 modules, but I can try to describe, which data you should send via SPI. This example is SPI slave. ESP-SPI-issue.zip

/ SPI SETTINGS on ESP32 side /

define COMM_SPI_HOST HSPI_HOST

define COMM_SPI_GPIO_HANDSHAKE 16

define COMM_SPI_GPIO_MOSI 12 / Output /

define COMM_SPI_GPIO_MISO 13 / Input /

define COMM_SPI_GPIO_SCLK 15

define COMM_SPI_GPIO_CS 14

SPI data protocol: 1 byte - 0x88 2 bytes - length x bytes - data

Maximum length of data is 64 with header (0x88 + length).

The ESP32 send response only, when the data is ok for tha protocol above. I don't want share the other protocols in my device.

This is my test on the FRDM kinetis side:

//TODO: START TEST!
uint8_t data[256];
uint32_t sent = 0;
uint32_t sent_all = 0;
for(int i=0; i<256; i++)
    data[i] = i;

tcs_esp32_connection_hw_reset();
tcs_timer_wait_ms(10000);

while(256-sent_all)
{
    if(comm_ctx.ready_to_send)
    {
        tcs_spi_send(data+sent_all, 256-sent_all, &sent);
        sent_all += sent;
    }
    /* Dummy recv for read data if possible */
    else if(comm_ctx.ready_to_recv)
    {
        printf("r\n");
        tcs_spi_recv();
    }
}
while(1){};
//TODO: END TEST!

static tcs_err_t tcs_spi_send(const uint8_t * data, uint32_t len, uint32_t * sent)
{
    dspi_status_t dspiResult;
    uint32_t wordsTransfer = 0;
    uint16_t tx_size = 0;

    uint8_t rx_tmp_buff[TCS_COMM_RX_TX_SIZE];
    uint8_t tx_tmp_buff[TCS_COMM_RX_TX_SIZE];

    *sent = 0;

    printf(".");

    /* Wait for interrupt, that tells all data received in slave */
    if(!comm_ctx.ready_to_send)
        return TCS_OK;

    printf("-");

    /* Not yet done latest operation. */
    if(DSPI_DRV_MasterGetTransferStatus(TCS_WIFI_DSPI_MASTER_INSTANCE, &wordsTransfer) != kStatus_DSPI_Success)
        return TCS_OK;

    printf("-");

    /* Sending, wait! */
    comm_ctx.ready_to_send = TCS_FALSE;

    tcs_memset(rx_tmp_buff, 0, TCS_COMM_RX_TX_SIZE);
    tcs_memset(tx_tmp_buff, 0, TCS_COMM_RX_TX_SIZE);

    tx_size = len;
    if(tx_size > TCS_COMM_RX_TX_SIZE-3)
        tx_size = TCS_COMM_RX_TX_SIZE-3;

    tcs_memcpy(tx_tmp_buff+3, data, tx_size);

    /* START byte */
    tx_tmp_buff[0] = 0x88;
    /* TX len */
    tx_tmp_buff[1] = TCS_LOBYTE(tx_size);
    tx_tmp_buff[2] = TCS_HIBYTE(tx_size);

    TCS_DEBUG_PRINTHEX(TCS_LOG_CATEGORY, "SPI sending data", tx_tmp_buff, TCS_COMM_RX_TX_SIZE );

    /* Send the data. */
    dspiResult = DSPI_DRV_MasterTransfer(TCS_WIFI_DSPI_MASTER_INSTANCE, NULL, tx_tmp_buff, rx_tmp_buff, TCS_COMM_RX_TX_SIZE);
    if (dspiResult != kStatus_DSPI_Success)
    {
        TCS_ERROR_PRINTF(TCS_LOG_CATEGORY, "SPI send error!");
        comm_ctx.ready_to_send = TCS_TRUE;
        return TCS_ERR_FAIL;
    }

    /* Wait for SPI transfer done (Because it can receive any data when sending! - This must be changed to non-blocking mode!) */
    while((dspiResult = DSPI_DRV_MasterGetTransferStatus(TCS_WIFI_DSPI_MASTER_INSTANCE, &wordsTransfer)) == kStatus_DSPI_Busy);

    if(dspiResult != kStatus_DSPI_Success)
        TCS_ERROR_PRINTF(TCS_LOG_CATEGORY, "SPI send/recv error (%d)!", dspiResult);
    else
        TCS_INFO_PRINTF(TCS_LOG_CATEGORY, "==SPI sent %d.", tx_size);

    /* If anything received when sending */
    if(/*wordsTransfer != 0 &&*/ rx_tmp_buff[0] == 0x88)
    {
        uint16_t rxlen = TCS_UINT16(rx_tmp_buff[1], rx_tmp_buff[2]);

        if(rxlen <= (TCS_COMM_RX_TX_SIZE-3) )
        {
            TCS_INFO_PRINTF(TCS_LOG_CATEGORY, "==SPI received %d in send.", rxlen);
            TCS_DEBUG_PRINTHEX(TCS_LOG_CATEGORY, "SPI received data", rx_tmp_buff, rxlen+3 );
            tcs_buffer_add(&comm_ctx.rx, rx_tmp_buff+3, rxlen, TCS_TRUE);
        }
    }

    *sent = tx_size;

    return TCS_OK;
}

static tcs_err_t tcs_spi_recv(void)
{
    dspi_status_t dspiResult;
    uint32_t wordsTransfer = 0;

    uint8_t rx_tmp_buff[TCS_COMM_RX_TX_SIZE];
    uint8_t tx_tmp_buff[TCS_COMM_RX_TX_SIZE];

    /* Wait for interrupt, that tells any data is pending in slave */
    if(!comm_ctx.ready_to_recv)
        return TCS_OK;

    /* Not yet done latest operation. */
    if(DSPI_DRV_MasterGetTransferStatus(TCS_WIFI_DSPI_MASTER_INSTANCE, &wordsTransfer) != kStatus_DSPI_Success /*kStatus_DSPI_Busy*/)
        return TCS_OK;

    tcs_memset(rx_tmp_buff, 0, TCS_COMM_RX_TX_SIZE);
    tcs_memset(tx_tmp_buff, 0, TCS_COMM_RX_TX_SIZE);

    /* Receive data. */
    dspiResult = DSPI_DRV_MasterTransfer(TCS_WIFI_DSPI_MASTER_INSTANCE, NULL, tx_tmp_buff, rx_tmp_buff, TCS_COMM_RX_TX_SIZE);
    if (dspiResult != kStatus_DSPI_Success)
    {
        TCS_ERROR_PRINTF(TCS_LOG_CATEGORY, "SPI send error!");
        return TCS_ERR_FAIL;
    }

    printf("rx\n");

    /* Receiving */
    comm_ctx.ready_to_recv = TCS_FALSE;

    /* Wait for SPI transfer done */
    while((dspiResult = DSPI_DRV_MasterGetTransferStatus(TCS_WIFI_DSPI_MASTER_INSTANCE, &wordsTransfer)) == kStatus_DSPI_Busy);

    if(dspiResult != kStatus_DSPI_Success)
        TCS_ERROR_PRINTF(TCS_LOG_CATEGORY, "SPI recv error (%d)!", dspiResult);

    /* Check first byte of received data, must be 0x88 */
    if(rx_tmp_buff[0] == 0x88)
    {
        uint16_t rxlen = TCS_UINT16(rx_tmp_buff[1], rx_tmp_buff[2]);

        TCS_INFO_PRINTF(TCS_LOG_CATEGORY, "==SPI received %d.", rxlen);

        if(rxlen <= (TCS_COMM_RX_TX_SIZE-3) )
        {

            TCS_INFO_PRINTF(TCS_LOG_CATEGORY, "==SPI received %d.", rxlen);
            TCS_DEBUG_PRINTHEX(TCS_LOG_CATEGORY, "SPI received data", rx_tmp_buff, rxlen+3 );

            tcs_buffer_add(&comm_ctx.rx, rx_tmp_buff+3, rxlen, TCS_TRUE);
        }
    }

    return TCS_OK;
}
zavovi commented 5 years ago

Hi, I am working on it and debugging and I changed handling of the handshake pin into main communication task and it seems, that it is working now.

This is my communication task now:

static void tcs_communication_rx_tx_task(void *pvParameter)
{
    tcs_err_t err;
    uint8_t * rx_data;
    uint8_t * tx_data;
    uint32_t tx_size = 0;

    comm_ctx.events = xEventGroupCreate();

    ESP_LOGI(TAG, "Starting RX/TX task...");

    if(comm_ctx.type == COMM_TYPE_UART)
    {
        /* Initialize UART */
        err = tcs_uart_init();
    }
    else if(comm_ctx.type == COMM_TYPE_SPI)
    {
        /* Initialize SPI */
        err = tcs_spi_init();
    }
    else
    {
        ESP_LOGE(TAG, "Bad communication type!\n");
        err = TCS_ERR_BADPARAM;
    }

    if(TCS_FAILED(err))
        goto ERROR;

    /* Prepare buffers */
    tcs_buffer_prepare(&comm_ctx.rx, TCS_COMM_RX_TX_SIZE);
    tcs_buffer_prepare(&comm_ctx.tx, TCS_COMM_RX_TX_SIZE);

    /* Prepare RX buffer */
    rx_data = heap_caps_malloc(TCS_COMM_RX_TX_SIZE+1, MALLOC_CAP_DMA);
    if(rx_data == NULL)
    {
        ESP_LOGE(TAG, "Error in malloc receive buffer.\n");
        err = TCS_ERR_NOMEM;
        goto ERROR;
    }

    /* Prepare TX buffer */
    tx_data = heap_caps_malloc(TCS_COMM_RX_TX_SIZE+1, MALLOC_CAP_DMA);
    if(tx_data == NULL)
    {
        ESP_LOGE(TAG, "Error in malloc transmit buffer.\n");
        err = TCS_ERR_NOMEM;
        goto ERROR;
    }

    memset(rx_data, 0, TCS_COMM_RX_TX_SIZE+1);
    memset(tx_data, 0, TCS_COMM_RX_TX_SIZE+1);

    comm_ctx.initialized = true;

    while(1)
    {
        if(comm_ctx.type == COMM_TYPE_UART)
        {
            int received = uart_read_bytes(COMM_UART_NUM, rx_data, TCS_COMM_RX_TX_SIZE, 10 / portTICK_RATE_MS);
            if(received < 0)
            {
                ESP_LOGE(TAG, "UART read bytes failed!\n");
                err = TCS_ERR_COMM;
            }
            else
            {

                /* Wait for not locked */
                while(tcs_buffer_is_locked(&comm_ctx.rx));

                /* Lock buffer */
                tcs_buffer_lock(&comm_ctx.rx);

                tcs_buffer_add(&comm_ctx.rx, rx_data, received, true);

                /* Unlock buffer */
                tcs_buffer_unlock(&comm_ctx.rx);

                /* set event for receive task */
                xEventGroupSetBits(comm_ctx.events, COMM_EVENT_RX);
            }
        }
        else if(comm_ctx.type == COMM_TYPE_SPI)
        {
            spi_slave_transaction_t t;

            if(comm_ctx.spi_pending)
                continue;

            memset(&t, 0, sizeof(t));

            memset(rx_data, 0, TCS_COMM_RX_TX_SIZE+1);
            memset(tx_data, 0, TCS_COMM_RX_TX_SIZE+1);

            tx_size = 0;

            t.length = TCS_COMM_RX_TX_SIZE*8;
            t.rx_buffer = rx_data;

            t.trans_len = 0;
            t.tx_buffer = NULL;

            /* Wait for not locked */
            while(tcs_buffer_is_locked(&comm_ctx.tx));

            /* Lock buffer */
            tcs_buffer_lock(&comm_ctx.tx);

            tx_size = tcs_buffer_get_used(&comm_ctx.tx);

            //tx_data[0] = 0;

            /* Copy TX data from context to transmit buffer */
            if(tx_size > 0)
            {
#if TCS_COMM_DEBUG_PRINT
                printf("TX%d\n", tx_size);
#endif
                if(tx_size > TCS_COMM_RX_TX_SIZE-3)
                    tx_size = TCS_COMM_RX_TX_SIZE-3;

                memcpy(tx_data+3, comm_ctx.tx.buffer, tx_size);

                /* START byte */
                tx_data[0] = 0x88;
                /* TX len */
                tx_data[1] = TCS_LOBYTE(tx_size);
                tx_data[2] = TCS_HIBYTE(tx_size);

                /* Consume buffer */
                tcs_buffer_consume(&comm_ctx.tx, tx_size);

#if TCS_COMM_DEBUG_PRINT
                //ESP_LOGI(TAG, "Transmit SPI data %d", tx_size);
                ESP_LOG_BUFFER_HEX(TAG, tx_data, tx_size+3);
#endif

                t.trans_len = (tx_size+3)*8;
                t.tx_buffer = tx_data;

            }

            /* Unlock buffer */
            tcs_buffer_unlock(&comm_ctx.tx);

            WRITE_PERI_REG(GPIO_OUT_W1TS_REG, (1<<COMM_SPI_GPIO_HANDSHAKE));
            comm_ctx.spi_pending = true;
            esp_err_t ret = spi_slave_transmit(COMM_SPI_HOST, &t,/* 100 / portTICK_RATE_MS*/portMAX_DELAY);
            if(ret == ESP_ERR_TIMEOUT)
            {
                ESP_LOGE(TAG, "SPI RX/TX timeout (0x%02x)!\n", ret);
                comm_ctx.spi_pending = false;
                /* Do nothing */
                continue;
            }
            else if(ret != ESP_OK)
            {
                comm_ctx.spi_pending = false;
                ESP_LOGE(TAG, "SPI RX/TX failed (0x%02x)!\n", ret);
                err = TCS_ERR_COMM;
            }
            else
            {
                /* Wait for not locked */
                while(tcs_buffer_is_locked(&comm_ctx.rx));

                /* Lock buffer */
                tcs_buffer_lock(&comm_ctx.rx);

                uint16_t rxlen = 0;
                if((t.trans_len/8) > 3 && rx_data[0] == 0x88)
                {
                    rxlen = TCS_UINT16(rx_data[1], rx_data[2]);
#if TCS_COMM_DEBUG_PRINT
                    ESP_LOGW(TAG, "SPI RX - %d.", t.trans_len/8);
#endif
                    //if(rxlen <= (t.trans_len-3) )
                    {
#if TCS_COMM_DEBUG_PRINT
                        //ESP_LOGI(TAG, "Received SPI data %d/%d", t.trans_len/8, TCS_COMM_RX_TX_SIZE);
                        ESP_LOG_BUFFER_HEX(TAG, rx_data, t.trans_len/8);

                        ESP_LOGW(TAG, "SPI RX (%d).", rxlen);
#endif
                        tcs_buffer_add(&comm_ctx.rx, rx_data+3, rxlen, true);
                    }
                }

                /* Unlock buffer */
                tcs_buffer_unlock(&comm_ctx.rx);

                /* set event for receive task */
                //if(rxlen > 0)
                    xEventGroupSetBits(comm_ctx.events, COMM_EVENT_RX);
            }
            WRITE_PERI_REG(GPIO_OUT_W1TC_REG, (1<<COMM_SPI_GPIO_HANDSHAKE));
            //rx_data[0] = 0;

        }
    }

ERROR:
    vTaskDelay(1000 / portTICK_PERIOD_MS);
    esp_restart();
}

And I removed handshake pin handling from the SPI callbacks. Now, I will try the maximum speed of the SPI.

ginkgm commented 4 years ago

@zavovi One thing you need to know is that, the SPI slave inside ESP32 is a totally Software-controlled one. Which means, the slave SW needs to configure the HW before the transaction actually happens, no matter sending or receiving.

If the master send at wrong time (when the slave HW is not ready), the master will not receive correct data from the slave, and no way to know it's incorrect. At the same the slave may not know the master has sent anything, and there's also no guarantee whats being sent to master/received from the master.

In short, a handshake line should always be used to ensure the slave is ready for next transaction.

ginkgm commented 4 years ago

Sorry for late reply, hope you have solved your issue...

About the requirement of coordinating the sending direction, we havn't come up with a simple solution. If you want to have a try, maybe you can try to use two transactions in a pair (both of them needs one handshake signal), and use the first transaction to indicate the direction...