首页 文章

SPI交易提前终止 - ESP-IDF

提问于
浏览
5

使用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 = 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);

1 回答

  • 0

    似乎以下警告 - 在SPI Slave driver documentation中找到 - 也适用于从主站接收数据的SPI主站:]

    警告:由于ESP32的设计特性,如果主机发送的字节数或从驱动器中传输队列的长度(以字节为单位)不大于8且可分为4,则SPI硬件无法将最后一个写入七个字节到接收缓冲区 .

    我现在改变了发送方,发送至少12个字节和4的倍数,问题就消失了 .

    如果你认为它只是因为运气而且我的假设是错误的,那就让我吧 .

相关问题