SPI 事务提前终止 - ESP-IDF

Posted

技术标签:

【中文标题】SPI 事务提前终止 - ESP-IDF【英文标题】:SPI transaction terminates early - ESP-IDF 【发布时间】:2018-08-27 03:26:11 【问题描述】:

使用 ESP-IDF (ESP32 SDK) 的 ESP32 应用与同一 SPI 总线上的两个 SPI 从设备(ILI9341 TFT 驱动器,NRF24L01+ 射频收发器)通信。总的来说,它工作得很好。但是,从 RF 收发器接收到的一些数据被截断,即只有前几个字节是正确的,其余的都是垃圾。

该问题或多或少具有重现性,并且仅在接收截断数据之前与其他从机(TFT 驱动程序)进行 SPI 通信时才会发生。

有问题的 SPI 事务是一个全双工事务,它发送一个命令字节和 10 个虚拟字节,同时接收 10 个字节。它使用 VSPI 总线和 DMA 通道 1。如果出现问题,只有前几个字节是正确的,而后 2 到 6 个字节是无效的(0 或虚拟字节的值)。

我深入研究了 SDK 代码 (spi_master.c),添加了调试代码并在 DMA 的 lldesc_t 结构中观察到了一个令人惊讶的值:

在事务开始时,它使用length = 0x0csize = 0x0c 进行初始化。 0x0c 是 12 个字节,即四舍五入到下一个字的 10 个字节。

在事务结束时,值为length = 0x07size = 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);

【问题讨论】:

除了从 nCS 线路到从机的电气问题之外,我知道无法提前终止 SPI 事务 - 也就是说,提前终止的唯一方法是主机停止计时一段时间原因。这暗示了其他设备 SPI 驱动程序代码的 DMA 完成中断中的代码不干净或错误,这些代码巧合地破坏了其他 DMA 通道的某些位。 BTW 系统如何检测交易结束? 我已将它连接到逻辑分析仪,并且 SPI 事务不会提前终止。似乎是 DMA 问题或处理不当的中断。 ESP-IDF 代码可以在github.com/espressif/esp-idf/blob/master/components/driver/… 找到。中断处理程序从第 405 行开始。不幸的是,我对 ESP32,尤其是 SPI 和 DMA 交互的了解有限。 【参考方案1】:

似乎在SPI Slave driver documentation 中发现的以下警告也适用于从从机接收数据的 SPI 主机:]

警告:由于 ESP32 的设计特殊性,如果 主机发送的字节数或传输队列的长度 从驱动程序,以字节为单位,不大于 8 并且 可被四除,SPI 硬件可能无法将最后一个写入 七个字节到接收缓冲区。

我现在已将发送方更改为发送至少 12 个字节和 4 的倍数,问题就消失了。

如果您认为它只是因为运气而起作用并且我的假设是错误的,请告诉我。

【讨论】:

考虑到您在 32 位架构上处理 DMA 的事实,对 4 字节增量的要求并非难以理解。您在数据长度方面的灵活性将在很大程度上取决于启用 DMA 的 SPI 驱动程序的实现方式。从您找到的注释中,听起来驱动程序的作者没有实现您最初编程的功能。这里与 STM32F7 SPI 和 DMA 外设有一些相似之处,特别是 STM32F7 SPI 外设上的 4 字节 FIFO - 所以这并非闻所未闻。 . .底线 - 您找到了解决方案。 我也遇到过这个问题(当你设置 dma_chan=0 并且不要使用 DMA 时它会立即消失),通过告诉 ESP32 读取 32 位从机只希望发送 16 位的事务——当然会丢弃最后 16 位。

以上是关于SPI 事务提前终止 - ESP-IDF的主要内容,如果未能解决你的问题,请参考以下文章

维护合同的良好提前终止费是多少? [关闭]

为啥我打印素数的代码会提前终止?

工人 puma 日志提前终止是啥意思,为啥会发生?

Codecs系列x265编码器(十三):自带的帧间提前终止算法

Codecs系列x265编码器(十三):自带的帧间提前终止算法

SQL Server查询优化器执行计划“语句提前终止的原因:超时”