Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SPI transaction terminates early - ESP-IDF

An ESP32 app using ESP-IDF (ESP32 SDK) communicates with two SPI slaves on the same SPI bus (ILI9341 TFT driver, NRF24L01+ RF transceiver). Overall, it works great. However, some of the data received from the RF transceiver is truncated, i.e. only the first few bytes are correct and the rest is garbage.

The problem is more or less reproducible and only occurs if there is SPI communication with the other slave (TFT driver) immediately before receiving the truncated data.

The problematic SPI transaction is a full-duplex transaction that sends a command byte and 10 dummy bytes while receiving 10 bytes. It uses the VSPI bus and DMA channel 1. If the problem occurs, only the first few bytes are correct while the last 2 to 6 bytes are invalid (0 or the value of the dummy bytes).

I dug into the SDK code (spi_master.c), added debug code and observed a surprising value in the DMA's lldesc_t struct:

At transaction start, it is initialized with length = 0x0c and size = 0x0c. 0x0c is 12 bytes, i.e. the 10 bytes rounded to the next word.

At transaction end, the values are length = 0x07 and size = 0x0c (length can vary slightly). So the transaction only reads 7 bytes and then somehow terminates. Or rather the DMA operations terminates.

  • Would you agree that the data indicates an early termination?
  • What could be the cause for the early termination?
  • Are there some registers that could indicate the cause of the problem?

The code is pretty straightforward:

uint8_t* buffer = heap_caps_malloc(32, MALLOC_CAP_DMA);

...

memset(buffer, CMD_NOP, len);
spi_transaction_t trx;
memset(&trx, 0, sizeof(spi_transaction_t));
trx.cmd = 0x61;
trx.tx_buffer = buffer;
trx.length = 8 * 10;
trx.rx_buffer = buffer;
trx.rxlength = 8 * 10;

esp_err_t ret = spi_device_transmit(spi_device, &trx);
like image 285
Codo Avatar asked Mar 18 '18 13:03

Codo


1 Answers

It seems that the following warning – found in the SPI Slave driver documentation – also applies to a SPI master receiving data from a slave:]

Warning: Due to a design peculiarity in the ESP32, if the amount of bytes sent by the master or the length of the transmission queues in the slave driver, in bytes, is not both larger than eight and dividable by four, the SPI hardware can fail to write the last one to seven bytes to the receive buffer.

I've now changed the sender side to send at least 12 bytes and multiples of 4 and the problem is gone.

Let me now if you think it just works because of luck and my assumption is wrong.

like image 159
Codo Avatar answered Nov 14 '22 09:11

Codo