使用 ESP-IDF(ESP32 SDK)的 ESP32 应用程序与同一 SPI 总线(ILI9341 TFT 驱动器、NRF24L01+ RF 收发器)上的两个 SPI 从设备进行通信。总的来说,它工作得很好。但是,从 RF 收发器接收到的一些数据会被截断,即只有前几个字节是正确的,其余的都是垃圾。
该问题或多或少是可重现的,并且仅当在接收截断数据之前立即与其他从设备(TFT 驱动程序)进行 SPI 通信时才会发生。
有问题的 SPI 事务是一个全双工事务,它发送一个命令字节和 10 个虚拟字节,同时接收 10 个字节。它使用 VSPI 总线和 DMA channel 1。如果出现问题,只有前几个字节是正确的,而后 2 到 6 个字节无效(0 或虚拟字节的值)。
我深入研究了 SDK 代码 ( spi_master.c
),添加了调试代码,并在 DMA 的 lldesc_t
中观察到了一个惊人的值。结构:
在事务开始时,它被初始化为 length = 0x0c
和 size = 0x0c
. 0x0c 是 12 个字节,即四舍五入到下一个字的 10 个字节。
在事务结束时,值为 length = 0x07
和 size = 0x0c
(长度可能略有不同)。所以事务只读取 7 个字节,然后以某种方式终止。或者更确切地说,DMA 操作终止。
问题?
代码非常简单:
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);
最佳答案
似乎以下警告 – 在 SPI Slave driver documentation 中找到– 也适用于从从设备接收数据的 SPI 主设备:]
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.
我现在已将发送方更改为发送至少 12 个字节和 4 的倍数,问题就消失了。
如果您认为它只是因为运气而起作用并且我的假设是错误的,那么现在让我来。
关于microcontroller - SPI 事务提前终止 - ESP-IDF,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49348228/