Page 1 of 1

「solved」Is there any problem with ESP32-C3 SPI running DMA function!

Posted: Thu Oct 14, 2021 7:13 am
by axwfae
I recently purchased ESP32-c3 for testing and found a strange problem!

After the DMA function of SPI is enabled, SPI will go wrong in a very strange way at this time!

(1) Do not use DMA, SPI reads and writes normally with a length of 64 bytes
(2) DMA is enabled, there is no limit to the size of writing, one byte of FIFO is used for reading, and the reading and writing are normal
(3) DMA is enabled, the size of reading is not limited, writing uses FIFO and one byte is read, reading and writing are normal


(4) Enabling DMA, the size of reading and writing is not limited. At this time, the reading is normal, but the first data written is normal (350byte), and all the data after that have errors. But at this time, it is normal to write in SPI FIFO mode (a byte write)!

That is to say, when DMA is enabled, SPI can only work normally by enabling the method (2) or (3) above, but in this way the DMA acceleration function is lost. It's not running (1) fast

In the same way, it is normal for SPI to enable DMA on ESP32-S2.

Remarks: The c3 I bought is version 2. I don’t know if it’s the version 2 chip! Unable to confirm because version 3 is not available!


Use IDF version as v4.3.1

boot log

Code: Select all

--- Quit: Ctrl+] | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---
ESP-ROM:esp32c3-20200918
Build:Sep 18 2020
rst:0x1 (POWERON),boot:0xd (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd6100,len:0x17c4
load:0x403ce000,len:0x8dc
load:0x403d0000,len:0x2984
entry 0x403ce000
I (32) boot: ESP-IDF v4.3.1-dirty 2nd stage bootloader
I (32) boot: compile time 16:15:06
I (32) boot: chip revision: 2
I (34) boot.esp32c3: SPI Speed      : 80MHz
I (39) boot.esp32c3: SPI Mode       : DIO
I (44) boot.esp32c3: SPI Flash Size : 2MB
I (49) boot: Enabling RNG early entropy source...
I (54) boot: Partition Table:
I (58) boot: ## Label            Usage          Type ST Offset   Length
I (65) boot:  0 nvs              WiFi data        01 02 00009000 00006000
I (72) boot:  1 phy_init         RF data          01 01 0000f000 00001000
I (80) boot:  2 factory          factory app      00 00 00010000 00080000
I (87) boot:  3 storage          Unknown data     01 81 00090000 00020000
I (95) boot: End of partition table
I (99) esp_image: segment 0: paddr=00010020 vaddr=3c060020 size=13fc4h ( 81860) map
I (120) esp_image: segment 1: paddr=00023fec vaddr=3fc8e800 size=01ce8h (  7400) load
I (121) esp_image: segment 2: paddr=00025cdc vaddr=40380000 size=0a33ch ( 41788) load
I (133) esp_image: segment 3: paddr=00030020 vaddr=42000020 size=572ach (357036) map
I (187) esp_image: segment 4: paddr=000872d4 vaddr=4038a33c size=042ech ( 17132) load
I (191) esp_image: segment 5: paddr=0008b5c8 vaddr=50000000 size=00010h (    16) load
I (198) boot: Loaded app from partition at offset 0x10000
I (199) boot: Disabling RNG early entropy source...
I (216) cpu_start: Pro cpu up.
I (228) cpu_start: Pro cpu start user code
I (228) cpu_start: cpu freq: 160000000
I (228) cpu_start: Application information:
I (231) cpu_start: Project name:     ethernet_iperf
I (237) cpu_start: App version:      1
I (241) cpu_start: Compile time:     Oct  6 2021 16:11:07
I (247) cpu_start: ELF file SHA256:  4f5f21638fb8ac48...
I (253) cpu_start: ESP-IDF:          v4.3.1-dirty
I (259) heap_init: Initializing. RAM available for dynamic allocation:
I (266) heap_init: At 3FC92550 len 0002DAB0 (182 KiB): DRAM
I (272) heap_init: At 3FCC0000 len 0001F260 (124 KiB): STACK/DRAM
I (279) heap_init: At 50000010 len 00001FF0 (7 KiB): RTCRAM
I (285) spi_flash: detected chip: generic
I (290) spi_flash: flash io: dio
I (294) sleep: Configure to isolate all GPIO pins in sleep state
I (300) sleep: Enable automatic switching of GPIO sleep configuration
I (308) cpu_start: Starting scheduler.
W (313) vfs_fat_spiflash: f_mount failed (13)
I (313) vfs_fat_spiflash: Formatting FATFS partition, allocation unit size=4096
E (323) vfs_fat_spiflash: f_mkfs failed (14)
E (323) eth_example: Failed to mount FATFS (ESP_FAIL)

Type 'help' to get the list of commands.
Use UP/DOWN arrows to navigate through command history.
Press TAB when typing command name to auto-complete.

Your terminal application does not support escape sequences.

Line editing and history features are disabled.

On Windows, try using Putty instead.

  spi rw test 100byte 1 ==>
 00  01  02  03  04  05  06  07  08  09  0a  0b  0c  0d  0e  0f
 10  11  12  13  14  15  16  17  18  19  1a  1b  1c  1d  1e  1f
 20  21  22  23  24  25  26  27  28  29  2a  2b  2c  2d  2e  2f
 30  31  32  33  34  35  36  37  38  39  3a  3b  3c  3d  3e  3f
 40  41  42  43  44  45  46  47  48  49  4a  4b  4c  4d  4e  4f
 50  51  52  53  54  55  56  57  58  59  5a  5b  5c  5d  5e  5f
 60  61  62  63
  spi rw test 100byte 2 ==>
 02  02  02  02  02  02  02  02  02  02  02  02  02  02  02  02
 02  02  02  02  02  02  02  02  02  02  02  02  02  02  02  02
 02  02  02  02  02  02  02  02  02  02  02  02  02  02  02  02
 02  02  02  02  02  02  02  02  02  02  02  02  02  02  02  02
 42  42  42  42  42  42  42  42  42  42  42  42  42  42  42  42
 42  42  42  42  42  42  42  42  42  42  42  42  42  42  42  42
 42  42  42  42 



Test code :
esp-idf\examples\ethernet\iperf

Enable DMA

Code: Select all

    ESP_ERROR_CHECK(spi_bus_initialize(CONFIG_EXAMPLE_ETH_SPI_HOST, &buscfg, 3));
Disable DMA

Code: Select all

    ESP_ERROR_CHECK(spi_bus_initialize(CONFIG_EXAMPLE_ETH_SPI_HOST, &buscfg, 0));

Test using DM9051 as an external SPI read and write device
esp-idf\components\esp_eth\src\esp_eth_mac_dm9051.c


Driver for SPI operation part

Code: Select all

/**
 * @brief write value to dm9051 internal register
 */
static esp_err_t dm9051_register_write(emac_dm9051_t *emac, uint8_t reg_addr, uint8_t value)
{
    esp_err_t ret = ESP_OK;
    spi_transaction_t trans = {
        .cmd = DM9051_SPI_WR,
        .addr = reg_addr,
        .length = 8,
        .flags = SPI_TRANS_USE_TXDATA
    };
    trans.tx_data[0] = value;
    if (dm9051_lock(emac)) {
        if (spi_device_polling_transmit(emac->spi_hdl, &trans) != ESP_OK) {
            ESP_LOGE(TAG, "%s(%d): spi transmit failed", __FUNCTION__, __LINE__);
            ret = ESP_FAIL;
        }
        dm9051_unlock(emac);
    } else {
        ret = ESP_ERR_TIMEOUT;
    }
    return ret;
}

/**
 * @brief write buffer to dm9051 internal memory
 */
static esp_err_t dm9051_memory_write(emac_dm9051_t *emac, uint8_t *buffer, uint32_t len)
{
    esp_err_t ret = ESP_OK;
    spi_transaction_t trans = {
        .cmd = DM9051_SPI_WR,
        .addr = DM9051_MWCMD,
        .length = len * 8,
        .tx_buffer = buffer
    };
    if (dm9051_lock(emac)) {
        if (spi_device_polling_transmit(emac->spi_hdl, &trans) != ESP_OK) {
            ESP_LOGE(TAG, "%s(%d): spi transmit failed", __FUNCTION__, __LINE__);
            ret = ESP_FAIL;
        }
        dm9051_unlock(emac);
    } else {
        ret = ESP_ERR_TIMEOUT;
    }
    return ret;
}

/**
 * @brief read buffer from dm9051 internal memory
 */
static esp_err_t dm9051_memory_read(emac_dm9051_t *emac, uint8_t *buffer, uint32_t len)
{
    esp_err_t ret = ESP_OK;
    spi_transaction_t trans = {
        .cmd = DM9051_SPI_RD,
        .addr = DM9051_MRCMD,
        .length = len * 8,
        .rx_buffer = buffer
    };
    if (dm9051_lock(emac)) {
        if (spi_device_polling_transmit(emac->spi_hdl, &trans) != ESP_OK) {
            ESP_LOGE(TAG, "%s(%d): spi transmit failed", __FUNCTION__, __LINE__);
            ret = ESP_FAIL;
        }
        dm9051_unlock(emac);
    } else {
        ret = ESP_ERR_TIMEOUT;
    }
    return ret;
}

#define SPI_NO_DMA_LEN  64
/**
 * @brief write buffer to dm9051 internal memory in no dma mode
 */
static esp_err_t dm9051_block_write(emac_dm9051_t *emac, uint8_t *buffer, uint32_t len)
{
    esp_err_t ret = ESP_OK;

    uint32_t  wlTx_cnt = 0;
    
    for(wlTx_cnt = 0; wlTx_cnt < len;  wlTx_cnt+= SPI_NO_DMA_LEN)
    {
    	if(ESP_OK != dm9051_memory_write(emac,buffer+wlTx_cnt, ((len - wlTx_cnt) > SPI_NO_DMA_LEN) ? SPI_NO_DMA_LEN :  (len - wlTx_cnt) ))
    	{
            return ESP_FAIL;
    	}
    }
    return ret;
}


static esp_err_t dm9051_one_write(emac_dm9051_t *emac, uint8_t *buffer, uint32_t len)
{
    esp_err_t ret = ESP_OK;

    uint32_t  wlTx_cnt = 0;
    
    for(wlTx_cnt = 0; wlTx_cnt < len;  wlTx_cnt++)
    {
    	if(ESP_OK != dm9051_register_write(emac, DM9051_MWCMD  , buffer[wlTx_cnt]))
    	{
            return ESP_FAIL;
    	}
    }
    return ret;
}

/**
 * @brief read buffer from dm9051 internal memory in no dma mode
 */
static esp_err_t dm9051_block_read(emac_dm9051_t *emac, uint8_t *buffer, uint32_t len)
{
   esp_err_t ret = ESP_OK;

    uint32_t  wlRx_cnt = 0;
    
    for(wlRx_cnt = 0; wlRx_cnt < len; wlRx_cnt+=SPI_NO_DMA_LEN)
    {
    	if(ESP_OK != dm9051_memory_read(emac,buffer+wlRx_cnt, ((len - wlRx_cnt) > SPI_NO_DMA_LEN) ? SPI_NO_DMA_LEN :  (len - wlRx_cnt) ))
    	{
            return ESP_FAIL;
    	}
    }
    
    return ret;
}


Test function code

Code: Select all

static esp_err_t spi_rw_test(emac_dm9051_t *emac)
{
    
    esp_err_t ret = ESP_OK;
        
    uint8_t tx_value[100];
    uint8_t rx_data[100];
    
    uint8_t  nCnt;
    
    for(nCnt = 0; nCnt <100; nCnt++)
    {
        tx_value[nCnt] = nCnt;
        rx_data[nCnt] = 0;
    }
    
//    MAC_CHECK(dm9051_block_write(emac, tx_value, 100) == ESP_OK, "write memory failed", err, ESP_FAIL);
    MAC_CHECK(dm9051_one_write(emac, tx_value, 100) == ESP_OK, "write memory failed", err, ESP_FAIL);
    
    MAC_CHECK(dm9051_block_read(emac, rx_data, 100) == ESP_OK, "read rx data failed", err, ESP_FAIL);
     
    printf("\n  spi rw test 100byte 1 ==>");
    for(nCnt = 0; nCnt <100; nCnt++)
    {
        if(0 == (nCnt % 16)) printf("\n");
        printf(" %02x ", rx_data[nCnt]);
        
        rx_data[nCnt] = 0;
        tx_value[nCnt] = nCnt + 2;
    }
    
//    MAC_CHECK(dm9051_block_write(emac, tx_value, 100) == ESP_OK, "write memory failed", err, ESP_FAIL);
    MAC_CHECK(dm9051_one_write(emac, tx_value, 100) == ESP_OK, "write memory failed", err, ESP_FAIL);
    
    MAC_CHECK(dm9051_block_read(emac, rx_data, 100) == ESP_OK, "read rx data failed", err, ESP_FAIL);

    printf("\n  spi rw test 100byte 2 ==>");
    for(nCnt = 0; nCnt <100; nCnt++)
    {
        if(0 == (nCnt % 16)) printf("\n");
        printf(" %02x ", rx_data[nCnt]);
        
//        rx_data[nCnt] = 0;
//        tx_value[nCnt] = nCnt + 2;
    }
    
err:
    return ret;    
}

Disable dma, 64byte block read and write , Pass

Code: Select all

  spi rw test 100byte 1 ==>
 00  01  02  03  04  05  06  07  08  09  0a  0b  0c  0d  0e  0f
 10  11  12  13  14  15  16  17  18  19  1a  1b  1c  1d  1e  1f
 20  21  22  23  24  25  26  27  28  29  2a  2b  2c  2d  2e  2f
 30  31  32  33  34  35  36  37  38  39  3a  3b  3c  3d  3e  3f
 40  41  42  43  44  45  46  47  48  49  4a  4b  4c  4d  4e  4f
 50  51  52  53  54  55  56  57  58  59  5a  5b  5c  5d  5e  5f
 60  61  62  63
  spi rw test 100byte 2 ==>
 02  03  04  05  06  07  08  09  0a  0b  0c  0d  0e  0f  10  11
 12  13  14  15  16  17  18  19  1a  1b  1c  1d  1e  1f  20  21
 22  23  24  25  26  27  28  29  2a  2b  2c  2d  2e  2f  30  31
 32  33  34  35  36  37  38  39  3a  3b  3c  3d  3e  3f  40  41
 42  43  44  45  46  47  48  49  4a  4b  4c  4d  4e  4f  50  51
 52  53  54  55  56  57  58  59  5a  5b  5c  5d  5e  5f  60  61
 62  63  64  65

Enable dma, 64byte block read , one byte write , Pass

Code: Select all

  spi rw test 100byte 1 ==>
 00  01  02  03  04  05  06  07  08  09  0a  0b  0c  0d  0e  0f
 10  11  12  13  14  15  16  17  18  19  1a  1b  1c  1d  1e  1f
 20  21  22  23  24  25  26  27  28  29  2a  2b  2c  2d  2e  2f
 30  31  32  33  34  35  36  37  38  39  3a  3b  3c  3d  3e  3f
 40  41  42  43  44  45  46  47  48  49  4a  4b  4c  4d  4e  4f
 50  51  52  53  54  55  56  57  58  59  5a  5b  5c  5d  5e  5f
 60  61  62  63
  spi rw test 100byte 2 ==>
 02  03  04  05  06  07  08  09  0a  0b  0c  0d  0e  0f  10  11
 12  13  14  15  16  17  18  19  1a  1b  1c  1d  1e  1f  20  21
 22  23  24  25  26  27  28  29  2a  2b  2c  2d  2e  2f  30  31
 32  33  34  35  36  37  38  39  3a  3b  3c  3d  3e  3f  40  41
 42  43  44  45  46  47  48  49  4a  4b  4c  4d  4e  4f  50  51
 52  53  54  55  56  57  58  59  5a  5b  5c  5d  5e  5f  60  61
 62  63  64  65

Enable dma, 64byte block read and write , Fail

Code: Select all

  spi rw test 100byte 1 ==>
 00  01  02  03  04  05  06  07  08  09  0a  0b  0c  0d  0e  0f
 10  11  12  13  14  15  16  17  18  19  1a  1b  1c  1d  1e  1f
 20  21  22  23  24  25  26  27  28  29  2a  2b  2c  2d  2e  2f
 30  31  32  33  34  35  36  37  38  39  3a  3b  3c  3d  3e  3f
 40  41  42  43  44  45  46  47  48  49  4a  4b  4c  4d  4e  4f
 50  51  52  53  54  55  56  57  58  59  5a  5b  5c  5d  5e  5f
 60  61  62  63
  spi rw test 100byte 2 ==>
 02  02  02  02  02  02  02  02  02  02  02  02  02  02  02  02
 02  02  02  02  02  02  02  02  02  02  02  02  02  02  02  02
 02  02  02  02  02  02  02  02  02  02  02  02  02  02  02  02
 02  02  02  02  02  02  02  02  02  02  02  02  02  02  02  02
 42  42  42  42  42  42  42  42  42  42  42  42  42  42  42  42
 42  42  42  42  42  42  42  42  42  42  42  42  42  42  42  42
 42  42  42  42

Re: Is there any problem with ESP32-C3 SPI running DMA function!

Posted: Fri Oct 15, 2021 1:09 am
by ESP_Sprite
What ESP-IDF version are you using? If it's not the latest master, would you mind trying that to see if the issue is still there? Do you have a minimal but complete project you can share so we can quickly replicate your problems?

Re: Is there any problem with ESP32-C3 SPI running DMA function!

Posted: Fri Oct 15, 2021 7:11 am
by axwfae
ESP_Sprite wrote:
Fri Oct 15, 2021 1:09 am
What ESP-IDF version are you using? If it's not the latest master, would you mind trying that to see if the issue is still there? Do you have a minimal but complete project you can share so we can quickly replicate your problems?

Thank you very much, the problem has been solved!

This is a problem with SDK V4.3.1. After updating to the master version, the problem is eliminated!

Code: Select all

mode=tcp-client sip=192.168.123.167:5001, dip=192.168.123.150:5001, interval=3, time=30
I (12646) iperf: Successfully connected

        Interval Bandwidth
   0-   3 sec       14.77 Mbits/sec
   3-   6 sec       15.38 Mbits/sec
  6-   9 sec       15.20 Mbits/sec
   9-  12 sec       15.42 Mbits/sec
  12-  15 sec       15.34 Mbits/sec
  15-  18 sec       15.34 Mbits/sec
  18-  21 sec       15.38 Mbits/sec
  21-  24 sec       15.34 Mbits/sec
  24-  27 sec       15.34 Mbits/sec
  27-  30 sec       15.38 Mbits/sec
   0-  30 sec       15.29 Mbits/sec
I (42656) iperf: TCP Socket client is closed.

Re: 「solved」Is there any problem with ESP32-C3 SPI running DMA function!

Posted: Sat Oct 16, 2021 3:39 am
by ESP_Sprite
Good to hear, thanks for the update!