esp-idf: Multi SPI configuration causes occasional corrupted data transfer (IDFGH-11187)
Answers checklist.
- I have read the documentation ESP-IDF Programming Guide and the issue is not addressed there.
- I have updated my IDF branch (master or release) to the latest version and checked that the issue is present there.
- I have searched the issue tracker for a similar issue and not found a similar issue.
IDF version.
v5.1.1-1-gd3c99ed3b8
Espressif SoC revision.
ESP32-D0WD-V3 (revision v3.0)
Operating System used.
Linux
How did you build your project?
VS Code IDE
If you are using Windows, please specify command line type.
None
Development Kit.
Custom Board
Power Supply used.
External 3.3V
What is the expected behavior?
Two SPI buses are used:
- The HSPI is configured as Master. A dm9051 controller is the slave. The driver for the dm9051 from the esp-idf is used.
- The VSPI is configured as Slave and communicates with another controller. Reliable data transfer on both configured SPI busses is expected.
What is the actual behavior?
The communication of HSPI master is unstable. Approx. 10% of the messages are corrupted somehow. This can be observed for both incoming and outgoing data: For incoming data over the MISO line, it can be observed that data on the SPI bus sent by dm9051 is correct (via Logic Analyzer), but partly faulty data can be found in the receive buffer. For outgoing data (MOSI), there is correct data in the send buffer, but partly faulty data can be observed on the SPI bus.
Steps to reproduce.
- Step Configuration of the HSPI Master:
#define IN_MODULE_nINT_PIN GPIO_NUM_4
#define SPI_MODULE_MISO_PIN GPIO_NUM_12
#define SPI_MODULE_MOSI_PIN GPIO_NUM_13
#define SPI_MODULE_CLK_PIN GPIO_NUM_14
#define SPI_MODULE_nCS_PIN GPIO_NUM_15
#define ETHERNET_SPI_HOST HSPI_HOST
#define ETHERNET_SPI_CLK 5000000
#define ETHERNET_DMA_CHAN 1
esp_err_t Ethernet_init(void)
{
esp_err_t esp_err;
esp_eth_mac_t *poEthMac = NULL;
esp_eth_phy_t *poEthPhy = NULL;
esp_err = Ethernet_initSpi();
esp_err = Ethernet_initMacPhyController(&poEthMac, &poEthPhy)
}
esp_err_t Ethernet_initSpi(void)
{
oEthernet.hSpiHandle = NULL;
spi_bus_config_t oBusConfig = {
.miso_io_num = SPI_MODULE_MISO_PIN,
.mosi_io_num = SPI_MODULE_MOSI_PIN,
.sclk_io_num = SPI_MODULE_CLK_PIN,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
};
ESP_ERROR_CHECK(spi_bus_initialize(ETHERNET_SPI_HOST, &oBusConfig, ETHERNET_DMA_CHAN));
return ESP_OK;
}
esp_err_t Ethernet_initMacPhyController(esp_eth_mac_t **poOutMac ,esp_eth_phy_t **poOutPhy)
{
eth_mac_config_t oMacConfig = ETH_MAC_DEFAULT_CONFIG();
eth_phy_config_t oPhyConfig = ETH_PHY_DEFAULT_CONFIG();
oPhyConfig.autonego_timeout_ms = 0;
oPhyConfig.phy_addr = 1;
oPhyConfig.reset_gpio_num = -1;
spi_device_interface_config_t oSpiDevConfig = {
.command_bits = 1,
.address_bits = 7,
.mode = 0,
.clock_speed_hz = ETHERNET_SPI_CLK,
.spics_io_num = SPI_MODULE_nCS_PIN,
.queue_size = 20
};
eth_dm9051_config_t oDm9051Config = ETH_DM9051_DEFAULT_CONFIG(ETHERNET_SPI_HOST, &oSpiDevConfig);
oDm9051Config.int_gpio_num = IN_MODULE_nINT_PIN;
*poOutMac = esp_eth_mac_new_dm9051(&oDm9051Config, &oMacConfig);
*poOutPhy = esp_eth_phy_new_dm9051(&oPhyConfig);
return ESP_OK;
}
- Step Configuration of the SPI Slave:
#define OUT_MSP_nINT_PIN GPIO_NUM_16
#define OUT_MSP_nRDY_PIN GPIO_NUM_32
#define SPI_MSP_MISO_PIN GPIO_NUM_19
#define SPI_MSP_MOSI_PIN GPIO_NUM_23
#define SPI_MSP_CLK_PIN GPIO_NUM_18
#define SPI_MSP_nCS_PIN GPIO_NUM_5
#define MSP_HOST VSPI_HOST
#define MSP_DMA_CHAN 2
esp_err_t Slave_init(uint32_t nMaxLen)
{
esp_err_t esp_err;
// Configuration for the SPI bus
spi_bus_config_t buscfg =
{
.mosi_io_num = SPI_MSP_MOSI_PIN,
.miso_io_num = SPI_MSP_MISO_PIN,
.sclk_io_num = SPI_MSP_CLK_PIN,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = nMaxLen,
.flags = SPICOMMON_BUSFLAG_SLAVE,
.intr_flags = ESP_INTR_FLAG_LOWMED
};
// Configuration for the SPI slave interface
spi_slave_interface_config_t slvcfg =
{
.spics_io_num = SPI_MSP_nCS_PIN,
.flags = 0,
.queue_size = 2, // at least 2
.mode = 1,
.post_setup_cb = &Msp_postSetupCb,
.post_trans_cb = &Msp_postTransCb
};
//Initialize SPI slave interface
esp_err = spi_slave_initialize(MSP_HOST, &buscfg, &slvcfg, MSP_DMA_CHAN);
return esp_err;
}
sdkconfig file: sdkconfig.txt
Debug Logs.
Here is an example of the observed data corruption:
Data in the buffer as passed to the dm9051 in (emac_dm9051_transmit()):
28 6b 35 b2 71 f9 a8 03 2a ee c4 67 08 00 45 00
00 54 9e ba 40 00 ff 01 f7 66 c0 a8 b2 1b c0 a8
b2 1a 00 00 00 c7 00 01 2f 5c 59 65 15 65 00 00
00 00 9b 3e 07 00 00 00 00 00 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
Data observed on the SPI bus via logic analyzer:
28 6B 35 B2 71 F9 A8 03 2A EE C4 67 08 00 45 00
00 54 9E BA 40 00 FF 01 F7 66 C0 A8 B2 1B C0 A8
B2 1A 00 00 00 C7 00 01 2F 5C 59 65 15 65 00 00
00 00 9B 00 00 9B 3E 07 00 00 00 00 00 10 11 12
13 00 00 00 00 9B 3E 07 00 00 00 00 00 10 11 12
13 00 00 00 00 9B 3E 07 00 00 00 00 00 10 11 12
13 00
More Information.
- The mentioned issue started showing after an update from idfv4.3 to idfv5.1. With idf4.3 the communication with the dm9051 over the HSPI master is working as expected.
- I tried the given ethernet example in idfv5.1 for the dm9051 with our hardware setup and its working fine
- I moved the shown initialization above to the ethernet example and it is still working fine
- When I deactivate the VSPI Slave, the HSPI master starts working without any issues
Is it possible that there is an issue on balancing the DMA usage? It seems that somehow the data is corrupted between the SPI bus and dm9051 send/receive buffer. At the same time I would not suspect a SPI issue, since the data is correct in most parts and the faulty parts are not arbitrary data (see log above).
About this issue
- Original URL
- State: open
- Created 9 months ago
- Comments: 40 (7 by maintainers)
IDF SPI team hide in corner and scare a lot 🤣
Hey @kostaond,
I assume that the cause for the 1-2% losses I still observe in the case where the buffer is configured to 204B in length is, that some of our messages transmitted by the SPI master are shorter than 204B. So there are still some occasions where the size of the buffer and the message don’t match.
Anyways, thank you very much for your effort so far. I will then wait for some information from the SPI team. Greetings
Hi again, are there any news on this issue you can share? Greetings
Ok, sorry. I didn’t get that you are talking about the length of the transmitted data. But this is also always Word aligned. This line in the master code ensures that the transmitted length is always a multiple of 4:
IDF5.0 is not tested. The issue occured while updating the code from IDFv4.3 to IDFv5.1 (the latest version at that time).
@lilalaunestift if I set
acDatabuffer to size greater than actual transmitted data from master, I am able to reproduce the issue. In other words:acData[256]and SPI frames transmitted from master are204B, I observe ping loss.acData[204]and SPI frames transmitted from master are204B, I do NOT observe ping loss.acData[256]and SPI frames transmitted from master are256B, I do NOT observe ping loss.This could be your workaround. However, something is probably wrong somewhere. I’ll pass it to SPI team. My work is done here since it is beyond my specialization… I’m responsible for Ethernet…
Very good question, they apply. I’m not sure if check is correctly implemented in code though. I asked SPI team to double check.
@lilalaunestift sorry for not replying, I was busy with other tasks. However, provided code still has room for uncertainty. We invested quite some time with the previous attempt using modified SPI Slave example. Therefore I would much appreciate, if you could provide fully functioning minimum project under which you are able to demonstrate the issue. We need to reproduce it at our side to move forward. I tried to discuss with team responsible for SPI and they indicated that the issue could be at HW design side (PCB)…