Page 1 of 2
SPI slave driver, last 4 Bytes missing (using DMA)
Posted: Thu Sep 20, 2018 7:25 am
by trancefreak
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
Re: SPI slave driver, last 4 Bytes missing (using DMA)
Posted: Tue Sep 25, 2018 10:53 am
by trancefreak
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)
Posted: Wed Oct 17, 2018 3:14 pm
by vpopescu
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 ?
Re: SPI slave driver, last 4 Bytes missing (using DMA)
Posted: Fri Oct 19, 2018 3:15 am
by ESP_Sprite
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.
Re: SPI slave driver, last 4 Bytes missing (using DMA)
Posted: Wed Jan 09, 2019 7:45 pm
by squonk11
@trancefreak : did you find a solution or workaround for this problem? Unfortunately I encounter the same problem...
Re: SPI slave driver, last 4 Bytes missing (using DMA)
Posted: Sat Jan 12, 2019 4:56 am
by zotikus
Hi,
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
};
If you go to spi_common.h, you can see that:
Code: Select all
//Maximum amount of bytes that can be put in one DMA descriptor
#define SPI_MAX_DMA_LEN (4096-4)
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.
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.
};
This worked for me, I am actually transfering and receiving 32,768+8 bytes @98,304Hz, without problem!
Hope it helps.
Re: SPI slave driver, last 4 Bytes missing (using DMA)
Posted: Sat Jan 12, 2019 5:24 am
by ESP_Sprite
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.
Re: SPI slave driver, last 4 Bytes missing (using DMA)
Posted: Sat Jan 12, 2019 4:36 pm
by squonk11
I am quite sure that my problem is related to this statement:
Also, master should write lengths which are a multiple of 4 bytes. Data longer than that will be discarded.
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.
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)
But I do not have any idea how to implement this because the documentation of the SPI in the reference manual does not giving the required information.
Re: SPI slave driver, last 4 Bytes missing (using DMA)
Posted: Sun Jan 13, 2019 11:45 am
by ESP_Sprite
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)
Posted: Sun Jan 13, 2019 12:59 pm
by squonk11
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?