SPI slave driver, last 4 Bytes missing (using DMA)

trancefreak
Posts: 8
Joined: Wed Sep 19, 2018 7:31 am

SPI slave driver, last 4 Bytes missing (using DMA)

Postby trancefreak » Thu Sep 20, 2018 7:25 am

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

trancefreak
Posts: 8
Joined: Wed Sep 19, 2018 7:31 am

Re: SPI slave driver, last 4 Bytes missing (using DMA)

Postby trancefreak » Tue Sep 25, 2018 10:53 am

Please, can someone from Espressif give an update on the issue why the last 4 Bytes are always missing?

vpopescu
Posts: 1
Joined: Wed Oct 17, 2018 2:27 pm

Re: SPI slave driver, last 4 Bytes missing (using DMA)

Postby vpopescu » Wed Oct 17, 2018 3:14 pm

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 ?

ESP_Sprite
Posts: 9772
Joined: Thu Nov 26, 2015 4:08 am

Re: SPI slave driver, last 4 Bytes missing (using DMA)

Postby ESP_Sprite » Fri Oct 19, 2018 3:15 am

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.

squonk11
Posts: 69
Joined: Wed Mar 01, 2017 6:53 pm
Location: Germany

Re: SPI slave driver, last 4 Bytes missing (using DMA)

Postby squonk11 » Wed Jan 09, 2019 7:45 pm

@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

zotikus
Posts: 3
Joined: Sat Oct 28, 2017 3:41 am

Re: SPI slave driver, last 4 Bytes missing (using DMA)

Postby zotikus » Sat Jan 12, 2019 4:56 am

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.

ESP_Sprite
Posts: 9772
Joined: Thu Nov 26, 2015 4:08 am

Re: SPI slave driver, last 4 Bytes missing (using DMA)

Postby ESP_Sprite » Sat Jan 12, 2019 5:24 am

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.

squonk11
Posts: 69
Joined: Wed Mar 01, 2017 6:53 pm
Location: Germany

Re: SPI slave driver, last 4 Bytes missing (using DMA)

Postby squonk11 » Sat Jan 12, 2019 4:36 pm

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.
"Whoever believes to be someone has stopped becoming someone"
Sokrates

ESP_Sprite
Posts: 9772
Joined: Thu Nov 26, 2015 4:08 am

Re: SPI slave driver, last 4 Bytes missing (using DMA)

Postby ESP_Sprite » Sun Jan 13, 2019 11:45 am

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.

squonk11
Posts: 69
Joined: Wed Mar 01, 2017 6:53 pm
Location: Germany

Re: SPI slave driver, last 4 Bytes missing (using DMA)

Postby squonk11 » Sun Jan 13, 2019 12:59 pm

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

Who is online

Users browsing this forum: Google [Bot] and 42 guests