SPI DMA bug on the P4
Posted: Fri Jan 10, 2025 2:21 pm
I am using the ESP32-P4-Function-EV-Board and have an application running that uses the SPI in slave mode. I am compiling it using the IDF 5.4 library and tools. It works fine in non-DMA mode with 64-byte packets for large transfers. I have a CRC on it and the CRC is good in this mode.
I am now trying to get the DMA working and it generally works for 512-byte packets for many packets, but once in a while I receive a bad packet. This makes it impossible to send a large transfer without at least one or two packets being bad.
I have followed the directions to ensure that the buffers and size value are on 64-bit boundaries, and as I mentioned, most of the packets arrive correctly.
Map file:
I have attached a screenshot from a comparison tool that shows an example where we receive a bad packet.
As you can see, this is not a noise problem but looks more like a driver problem. I am sending a repeating pattern so that I can see the errors. The slash marks in the picture delineate the beginning of the actual data after my header. The left side is the packet that was sent. The packet on the right is the bad packet that was received on the P4.
The circle on the left shows 3 bytes that are missing from the packet on the right. The circle on the right side shows 3 bytes that were inserted incorrectly into the buffer and repeated from the 3 bytes before it.
I am fairly certain that this is some kind of hardware or library issue. As I mentioned, almost all of the packets arrive correctly and this only happens often enough to disallow large transfers. I am trying to send 200K and this happens about one to three times in that transfer.
I should also mention that in IDF 5.2.2, there is code to disallow SPI DMA transfer with a note about IDF-7503. But this code is changed in IDF 5.4, so I assume that it is now allowed:
See attachment showing the issue.
I am now trying to get the DMA working and it generally works for 512-byte packets for many packets, but once in a while I receive a bad packet. This makes it impossible to send a large transfer without at least one or two packets being bad.
I have followed the directions to ensure that the buffers and size value are on 64-bit boundaries, and as I mentioned, most of the packets arrive correctly.
Code: Select all
// SPI DMA buffers and lengths must be aligned to 64-but boundaries
#define ALIGNMENT_64Bit 64
__attribute__((aligned(ALIGNMENT_64Bit))) SRE_Packet_t workingSendPacket;
__attribute__((aligned(ALIGNMENT_64Bit))) SRE_Packet_t workingRcvPacket;
__attribute__((aligned(ALIGNMENT_64Bit))) const size_t SPIBufferSize = SRE_SPI_PACKET_SIZE;
Code: Select all
.srodata.SPIBufferSize
0x00000000 0x4 esp-idf/SPI_task/libSPI_task.a(SPI_task.c.obj)
.bss.workingRcvPacket
0x4ff510c0 0x40 esp-idf/SPI_task/libSPI_task.a(SPI_task.c.obj)
0x4ff510c0 workingRcvPacket
.bss.workingSendPacket
0x4ff51100 0x40 esp-idf/SPI_task/libSPI_task.a(SPI_task.c.obj)
0x4ff51100 workingSendPacket
As you can see, this is not a noise problem but looks more like a driver problem. I am sending a repeating pattern so that I can see the errors. The slash marks in the picture delineate the beginning of the actual data after my header. The left side is the packet that was sent. The packet on the right is the bad packet that was received on the P4.
The circle on the left shows 3 bytes that are missing from the packet on the right. The circle on the right side shows 3 bytes that were inserted incorrectly into the buffer and repeated from the 3 bytes before it.
I am fairly certain that this is some kind of hardware or library issue. As I mentioned, almost all of the packets arrive correctly and this only happens often enough to disallow large transfers. I am trying to send 200K and this happens about one to three times in that transfer.
I should also mention that in IDF 5.2.2, there is code to disallow SPI DMA transfer with a note about IDF-7503. But this code is changed in IDF 5.4, so I assume that it is now allowed:
Code: Select all
if (use_dma) {
#if CONFIG_IDF_TARGET_ESP32P4
abort(); //will supported in IDF-7503
#endif