microcontroller - SPI 事务提前终止 - ESP-IDF

标签 microcontroller spi freertos esp32

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

    最佳答案

    似乎以下警告 – 在 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/

    相关文章:

    c++ - mbed 中的 Hello World MQTT 程序

    c - 多个线程使用外围例程调用相同的函数

    spi - STM32f4 SPI DMA接收

    freertos - 如何理解uxtaskgetstackhighlwatermark()的返回值

    embedded - vTaskCreatePinnedToCore() 的行为不符合预期

    c - TickGetDiv256() 是如何工作的?

    c++ - 如何解释以下 C(包括位字段和结构)

    assembly - 有什么可能的方法来重新编程 USB 驱动器的微 Controller 吗?

    Python - 如何使用 ioctl 或 spidev 从设备读取输入?

    c - 用于嵌入式系统的小型 libc