weird SPI transfer on ESP32-C3 [IDFGH-5411]

zolinux
Posts: 1
Joined: Mon Jun 07, 2021 9:01 pm

weird SPI transfer on ESP32-C3 [IDFGH-5411]

Postby zolinux » Mon Jun 07, 2021 9:48 pm

Hi,

I have a small program to repeatedly send a buffer followed by receive a buffer via SPI2 with DMA enabled. If I disable the receiving part of the TRX function (by setting condition to "false" in second "if" statement), everything is fine, but otherwise only first time after boot-up the buffer will be sent correctly, all subsequent transmission will lead to transmit the first byte from the buffer so many times, that that long the buffer-to-send is:

Good transmission:
mosi-ok.png
mosi-ok.png (17.29 KiB) Viewed 2975 times
Bad transmission:
mosi-bad.png
mosi-bad.png (10.98 KiB) Viewed 2975 times
Basically it looks like the DMA engine "forgets" to increment the source address during sending the data out.

Code:

Code: Select all


static const spi_host_device_t SpiHost = SPI2_HOST; // SPI Host to use for communication to XXX chip
static const gpio_num_t XxxIrqPin = 5;              // Irq pin
static const gpio_num_t XxxnCsPin = 4;              // Chip select pin
static const size_t MaxTxBytesSpiTRxLen = 512;      // Max SPI frame length

static const spi_bus_config_t SpiBusConfig = {
    .mosi_io_num = 7,
    .miso_io_num = 2,
    .sclk_io_num = 6,
    .quadwp_io_num = -1,
    .quadhd_io_num = -1,
    .max_transfer_sz = MaxTxBytesSpiTRxLen,
    .flags = SPICOMMON_BUSFLAG_MASTER | SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MISO |
             SPICOMMON_BUSFLAG_MOSI,
    .intr_flags = 0,
};

static const spi_device_interface_config_t spiConfig = {
    .mode = 0,
    .clock_speed_hz = SPI_MASTER_FREQ_8M,
    .spics_io_num = -1,
    .queue_size = 5,
    .post_cb = NULL,
};

static const gpio_config_t IrqPinConfig = {
    .pin_bit_mask = 1 << XxxIrqPin,
    .mode = GPIO_MODE_INPUT,
    .pull_up_en = GPIO_PULLUP_DISABLE,
    .pull_down_en = GPIO_PULLDOWN_DISABLE,
    .intr_type = GPIO_INTR_POSEDGE,
};

static const gpio_config_t IrqnCsConfig = {
    .pin_bit_mask = 1 << XxxnCsPin,
    .mode = GPIO_MODE_INPUT_OUTPUT,
    .pull_up_en = GPIO_PULLUP_DISABLE,
    .pull_down_en = GPIO_PULLDOWN_DISABLE,
    .intr_type = GPIO_INTR_DISABLE,
};

struct hal{
    uint8_t *spiBuf;
    spi_device_handle_t spiDev;
} platform;

status_t TRx(struct hal *plat, uint8_t *txBuf[], size_t txLen[], size_t numTxBuffers,
    uint8_t *rxBuf[], size_t *rxLen[], size_t numRxBuffers)
{
    UNUSED(plat);
    ESP_ERROR_CHECK(gpio_set_level(XxxnCsPin, 0)); // assert chip select
    esp_task_wdt_reset();
    size_t bufIdx = 0;
    if (numTxBuffers && txBuf && txLen)
    {
        while (bufIdx < numTxBuffers)
        {
            spi_transaction_t txT;
            const uint8_t *buf = txBuf[bufIdx];
            assert(buf);
            const size_t bufLen = txLen[bufIdx];
            assert(bufLen < MaxTxBytesSpiTRxLen);

            memset(&txT, 0, sizeof(txT));
            txT.tx_buffer = buf;
            txT.length = bufLen * 8;

            // copy tx data to DMA capable memory
            ESP_LOGD(__func__, "(%u) <<", bufLen);
            dumpMemory("X", buf, bufLen);

            ESP_ERROR_CHECK(spi_device_transmit(platform.spiDev, &txT));
            bufIdx++;
        }
    }
    irqState = false;

    // Now receiving some data
    if (true && numRxBuffers && rxBuf && rxLen)
    {
        bufIdx = 0;
        while (bufIdx < numRxBuffers)
        {
            spi_transaction_t rxT;
            uint8_t *buf = rxBuf[bufIdx];
            assert(buf);
            const size_t bufLen = *rxLen[bufIdx];
            assert(bufLen < MaxTxBytesSpiTRxLen);

            memset(platform.spiBuf, 0, bufLen);
            memset(&rxT, 0, sizeof(rxT));
            rxT.rx_buffer = platform.spiBuf;
            rxT.length = bufLen * 8;
            rxT.rxlength = 0;
            ESP_ERROR_CHECK(spi_device_transmit(platform.spiDev, &rxT));
            ESP_LOGD(__func__, "(%u) >>", bufLen);
            dumpMemory(__func__, platform.spiBuf, bufLen);
            // memcpy(buf, platform.spiBuf, bufLen);

            bufIdx++;
        }
    }

    ESP_ERROR_CHECK(gpio_set_level(XxxnCsPin, 1)); // de-assert chip select
    return 0;
}

status_t Init()
{
    memset(&platform, 0, sizeof(platform));

    // XXX Irq pin
    ESP_ERROR_CHECK(gpio_config(&IrqnCsConfig));
    ESP_ERROR_CHECK(gpio_set_level(XxxnCsPin, 1));
    ESP_ERROR_CHECK(gpio_config(&IrqPinConfig));
    ESP_ERROR_CHECK(gpio_isr_handler_add(XxxIrqPin, &irqIsr, &platform));

    // allocate DMA capable memory
    platform.spiBuf = heap_caps_malloc(MaxTxBytesSpiTRxLen, MALLOC_CAP_DMA | MALLOC_CAP_32BIT);
    assert(platform.spiBuf);

    // init SPI driver
    ESP_ERROR_CHECK(spi_bus_initialize(SpiHost, &SpiBusConfig, SPI_DMA_CH_AUTO));
    ESP_ERROR_CHECK(spi_bus_add_device(SpiHost, &spiConfig, &platform.spiDev));

    ESP_ERROR_CHECK(gpio_intr_enable(XxxIrqPin));

    esp_log_level_set("*", ESP_LOG_VERBOSE);
    ESP_LOGD(__func__, "done");
    return 0;
}

void app_main(void)
{
    uint8_t txBuf[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // data will be transmitted
    uint8_t *tx[] = {txBuf};
    size_t txL[] = {sizeof(txBuf)};

    uint8_t rxBuf[128];     // receive buffer
    uint8_t *rx[] = {rxBuf};
    size_t rxLength = 2;    // 2 bytes to receive
    size_t *rxL[] = {&rxLength};

    ESP_ERROR_CHECK(gpio_install_isr_service(ESP_INTR_FLAG_IRAM));
    Init();

    while (true)
    {
        TRx(plat, tx, txL, 1, rx, rxL, 1);
        // TRx(plat, tx, txL, 1, NULL, NULL, 0);
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}
For debugging, the buffer gets dumped via "dumpMemory()" to serial monitor and the content is always correct.
I am using almost the latest ESP-IDF cloned from GitHub with an ESP32-C3-DevKitM-1. I would be very happy if someone could help me finding the root cause and fixing the problem.

Thanks,
zolinux

ESP_Alvin
Posts: 195
Joined: Thu May 17, 2018 2:26 am

Re: weird SPI transfer on ESP32-C3 [IDFGH-5411]

Postby ESP_Alvin » Wed Jun 16, 2021 3:31 am

Moderator's note: edit the topic title for issue tracking, thanks for reporting.

axellin
Posts: 197
Joined: Mon Sep 17, 2018 9:09 am

Re: weird SPI transfer on ESP32-C3 [IDFGH-5411]

Postby axellin » Wed Jun 16, 2021 3:54 am

ESP_Alvin wrote:
Wed Jun 16, 2021 3:31 am
Moderator's note: edit the topic title for issue tracking, thanks for reporting.
Hi ESP_Alvin,

This issue is reported publicly via the forum.
Is it possible to make IDFGH-5411 publicly access?
(Actually I had asked this before)

The thing is when the issue is fixed and the commit log has "Closes: IDFGH-5411"
I cannot find what is "IDFGH-5411".
And it's difficult to link back to the original report on the forum.
i.e. sometimes I even didn't know what was fixed and the impact.
So it's not clear if my application firmware needs update or not.

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

Re: weird SPI transfer on ESP32-C3 [IDFGH-5411]

Postby ESP_Sprite » Wed Jun 16, 2021 6:33 am

IDFGH-* issues are tracked on our internal Jira server and not public, sorry. We're working on also referring to the Github issue that originally triggered it in our commit messages.

Who is online

Users browsing this forum: Google [Bot] and 127 guests