使用ESP-IDF(ESP32 SDK)的ESP32应用程序与同一SPI总线上的两个SPI从机(ILI9341 TFT驱动程序,NRF24L01+ RF收发器)通信。总体而言,它工作得很好。然而,从RF收发器接收到的一些数据被截断了,即只有前几个字节是正确的,其余都是垃圾。
问题或多或少可以重现,仅在立即在接收截断数据之前与另一个从设备(TFT驱动程序)进行SPI通信时才会发生。
有问题的SPI事务是一个全双工事务,发送一个命令字节和10个虚拟字节,同时接收10个字节。它使用VSPI总线和DMA通道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);