Skip to content

[Bug] STM32的SPI驱动在DMA 全双工模式下 recv_buf 数据未更新的问题 #10716

@zx115

Description

@zx115

RT-Thread Version

5.1.0

Hardware Type/Architectures

STM32F407VGT6

Develop Toolchain

MDK Keil

Describe the bug

现象复现:

  1. 在menuconfig界面下使能BSP_SPIx_TX_USING_DMABSP_SPIx_RX_USING_DMA

  2. 使用rt_malloc()函数申请两块内存:tx_data(>=10)和rx_data(>=10);

  3. 将目标SPI总线的MISO接口拉高或拉低;

  4. 调用rt_spi_transfer函数向SPI设备发送>=10字节的数据,使用上一步申请的内存tx_data和rx_data分别作为发送缓存和接收缓存;

  5. 打印rx_data中的内容,发现内容不符合预期。期望结果应为rx_data的值全为0xFF(MISO接口拉高)或0x00(MISO接口拉低),而实际则为内存中未更新的随机数据。

问题定位:

问题出在 rt-thread-5.1.0/bsp/stm32/libraries/HAL_Drivers/drivers/drv_spi.cspixfer函数中。

原因分析:

  • 348行到374行的分析:
Image

在启用TX_DMA的情况下,为了提高DMA的效率,该函数对send_buf的值(即发送缓冲区的地址)做了对齐4字节的操作,当send_buf的值恰巧对齐4字节时,直接将send_buf的值赋给p_txrx_buffer;当不对齐时,则通过rt_malloc()函数重新申请一块内存(该函数能够保证生成的内存对齐4字节),并将该地址赋给p_txrx_buffe,同时也保存一份副本在dma_aligned_buffer变量里(在此之前该变量的值为RT_NULL)。

  • 383行的分析:
Image

在TX_DMA和RX_DMA皆启用的情况下,数据的传输实际上是调用了HAL_SPI_TransmitReceive_DMA函数实现的。但是在这个驱动中使用p_txrx_buffe同时作为HAL_SPI_TransmitReceive_DMA的TX和RX缓存,也就是说HAL_SPI_TransmitReceive_DMA在发送p_txrx_buffe中的数据的同时也在将接收到的数据写入其中,这本身并没有太大问题,只要后面再将接收到的数据复制回recv_buf中就行。

  • 468行到482行的分析:
Image

但是这个函数并不是在任何情况下都会将接收到的数据复制回recv_buf中,而是只在dma_aligned_buffer != RT_NULL的情况下才会执行rt_memcpy(recv_buf, p_txrx_buffer, send_length);语句将数据复制回去。这里的dma_aligned_buffer就是前面提到的重新申请的内存的副本。只有当send_buf的值不对齐4字节时,dma_aligned_buffer才会保存一份重新申请的内存的副本,而如果send_buf的值恰巧对齐4字节,dma_aligned_buffer将维持初始值RT_NULL,此时rt_memcpy(recv_buf, p_txrx_buffer, send_length);语句也将无法得到执行,于是就造成了recv_buf不更新的bug。

其他问题:

事实上,这份驱动还有其他问题。例如,如果你只使能了TX_DMA而未使能RX_DMA,则spixfer则只使用语句HAL_SPI_Transmit_DMA(spi_handle, (uint8_t *)p_txrx_buffer, send_length);将数据发送出去,而完全抛弃了接收数据。在这种情况下使用rt_spi_transfer传输数据依然会出现接收数据错误的问题。

Other additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions