SPI slave driver, last 4 Bytes missing (using DMA)
-
- Posts: 8
- Joined: Wed Sep 19, 2018 7:31 am
SPI slave driver, last 4 Bytes missing (using DMA)
Hi,
I'm using the spi slave driver and I have the problem that the last 4 Bytes are not written to the RX buffer. The trans_len field shows that all bytes are received. I tried all available SPI modes (0 - 3). This issue happens in all modes. I use DMA and the size of the transaction does not matter. It happens with 64 bytes or 8196 and all other transaction sizes (all dividable by 4).
As a workaround I send 4 dummy bytes to make sure my data is completely written to the buffers
Is this a bug and is there already a fix for it?
Just for info: The frequency does not matter, it happens with 10kHz and also with 10 MHz and frequencies in between. I checked the output of the master (Raspberry PI) with a logic analyzer and the output is ok, all bytes written and correect. The trans_len field proves that all bytes are received. But the last 4 bytes do not show up in the RX buffer.
Thanks,
Christian
I'm using the spi slave driver and I have the problem that the last 4 Bytes are not written to the RX buffer. The trans_len field shows that all bytes are received. I tried all available SPI modes (0 - 3). This issue happens in all modes. I use DMA and the size of the transaction does not matter. It happens with 64 bytes or 8196 and all other transaction sizes (all dividable by 4).
As a workaround I send 4 dummy bytes to make sure my data is completely written to the buffers
Is this a bug and is there already a fix for it?
Just for info: The frequency does not matter, it happens with 10kHz and also with 10 MHz and frequencies in between. I checked the output of the master (Raspberry PI) with a logic analyzer and the output is ok, all bytes written and correect. The trans_len field proves that all bytes are received. But the last 4 bytes do not show up in the RX buffer.
Thanks,
Christian
-
- Posts: 8
- Joined: Wed Sep 19, 2018 7:31 am
Re: SPI slave driver, last 4 Bytes missing (using DMA)
Please, can someone from Espressif give an update on the issue why the last 4 Bytes are always missing?
Re: SPI slave driver, last 4 Bytes missing (using DMA)
Hello, I am having the same issue using the ESP32 WROVER as slave, maximum buffer size to have a valid transfer on SPI, using DMA, between master and slave, is 4092. There is one place where is specified that the DMA buffer size is limited at 4092 byte, "Because limited of DMA buffer is 4092 bytes" line 378, file Drivers\esp-idf\components\driver\i2s.c, so it is this a known bug, or a limitation ?
-
- Posts: 9764
- Joined: Thu Nov 26, 2015 4:08 am
Re: SPI slave driver, last 4 Bytes missing (using DMA)
Trancefreak: Are you sure your /CS doesn't go high before the last few bytes have been written? The ESP32 hardware doesn't really like the /CS-pin going high early and can abort the transfer, causing what you see.
vpopescu: No idea what you're trying to say here, but both SPI master as well as slave drivers support a max_transfer_sz option to indicate how many DMA buffers to allocate; you can set this as high as you want and in that way transfer more than the 4092 bytes that fit in one DMA buffer.
vpopescu: No idea what you're trying to say here, but both SPI master as well as slave drivers support a max_transfer_sz option to indicate how many DMA buffers to allocate; you can set this as high as you want and in that way transfer more than the 4092 bytes that fit in one DMA buffer.
Re: SPI slave driver, last 4 Bytes missing (using DMA)
@trancefreak : did you find a solution or workaround for this problem? Unfortunately I encounter the same problem...
"Whoever believes to be someone has stopped becoming someone"
Sokrates
Sokrates
Re: SPI slave driver, last 4 Bytes missing (using DMA)
Hi,
When configuring spi_bus_config_t, by default max_transfer_sz, is 4094 Bytes.
i.g.
If you go to spi_common.h, you can see that:
It actually reserves 4 bytes for data transfer.
Those 4 bytes AFAIK are for referencing, therefore, if you need a longer transfer sz than 4092 bytes, then you should do .max_transfer_sz=bytes_need+4
ig.
This worked for me, I am actually transfering and receiving 32,768+8 bytes @98,304Hz, without problem!
Hope it helps.
When configuring spi_bus_config_t, by default max_transfer_sz, is 4094 Bytes.
i.g.
Code: Select all
spi_bus_config_t buscfg={
.miso_io_num=PIN_NUM_MISO,
.mosi_io_num=PIN_NUM_MOSI,
.sclk_io_num=PIN_NUM_CLK,
.quadwp_io_num=-1,
.quadhd_io_num=-1,
.max_transfer_sz=0 //in bytes, default is 4094
};
Code: Select all
//Maximum amount of bytes that can be put in one DMA descriptor
#define SPI_MAX_DMA_LEN (4096-4)
Those 4 bytes AFAIK are for referencing, therefore, if you need a longer transfer sz than 4092 bytes, then you should do .max_transfer_sz=bytes_need+4
ig.
Code: Select all
spi_bus_config_t buscfg={
.miso_io_num=PIN_NUM_MISO,
.mosi_io_num=PIN_NUM_MOSI,
.sclk_io_num=PIN_NUM_CLK,
.quadwp_io_num=-1,
.quadhd_io_num=-1,
.max_transfer_sz=4096+4 //if 4096 bytes needed.
};
Hope it helps.
-
- Posts: 9764
- Joined: Thu Nov 26, 2015 4:08 am
Re: SPI slave driver, last 4 Bytes missing (using DMA)
The '+4' is not needed. The max DMA length is 4096-4 because it's a 12-bit number, and for ease of use we assume most DMA descriptors will use a multiple of 32 bit. This means the DMA length can go from 0 to 0xffc, or 0 to (4096-4). Note that this is an internal hardware detail that is entirely abstracted away by the SPI driver. In general, you can assume that whatever value of max_transfer_sz you hand to the SPI driver, the SPI driver will guarantee you can send transactions of that size or smaller.
As I said before, for people who run into issues like this: check your /cs signal. The SPI slave logic assumes the /cs signal goes high after the transaction is finished. If for whatever reason (clock slew, difference in wire length, whatever) the ESP32 sees the /cs signal going high before the transaction is done, it aborts the transaction in a weird way that can cause the last 4 bytes to get corrupted or not written.
As I said before, for people who run into issues like this: check your /cs signal. The SPI slave logic assumes the /cs signal goes high after the transaction is finished. If for whatever reason (clock slew, difference in wire length, whatever) the ESP32 sees the /cs signal going high before the transaction is done, it aborts the transaction in a weird way that can cause the last 4 bytes to get corrupted or not written.
Re: SPI slave driver, last 4 Bytes missing (using DMA)
I am quite sure that my problem is related to this statement:
So I am currently badly searching for a solution for this problem because I urgently need it. Do you have any hint for me? The possibilities I currently see are:
which can be found here: https://docs.espressif.com/projects/esp ... slave.html. Unfortunately I have absolutely no influence on the amount of data the master is sending - it is any number of bytes between 4 and 114. Due to this neither the DMA transfer mode nor the mode without DMA (using the internal buffer of the SPI interface) works for me. ESP-IDF currently does not offer any other possibility to read data from SPI in slave mode.Also, master should write lengths which are a multiple of 4 bytes. Data longer than that will be discarded.
So I am currently badly searching for a solution for this problem because I urgently need it. Do you have any hint for me? The possibilities I currently see are:
- polling: waiting and reading the SPI byte by byte
- getting the data byte by byte via interrupt (preferred)
"Whoever believes to be someone has stopped becoming someone"
Sokrates
Sokrates
-
- Posts: 9764
- Joined: Thu Nov 26, 2015 4:08 am
Re: SPI slave driver, last 4 Bytes missing (using DMA)
No, to my knowledge, that is a known bug of the SPI slave used in DMA mode: you need to somehow know the amount of bytes that are transmitted, or use a multiple of 4 bytes, or you'll run into corruption of the last bytes.
Re: SPI slave driver, last 4 Bytes missing (using DMA)
The information about the amount of transfered bytes from the master is stored in the second byte of the transferred telegram. In order to read this I need to receive the first two bytes separately (or byte by byte). Is there any possibility to achieve that? Even if that needs to be done by polling?
"Whoever believes to be someone has stopped becoming someone"
Sokrates
Sokrates
Who is online
Users browsing this forum: No registered users and 139 guests