ST意法半导体
直播中

李俊

8年用户 1399经验值
私信 关注
[问答]

使用H723的SPI6+BDMA组合,通信过程经常报UDR和OVR错误中断怎么解决?

使用H723的SPI6+BDMA组合。通信过程经常报UDR和OVR错误中断。有时直接卡住,无法通信。

回帖(3)

郭大

2025-3-3 11:56:39

针对STM32 H723使用SPI6+BDMA时频繁出现UDR(Underrun)和OVR(Overrun)错误的问题,以下是逐步解决方案:




1. 降低SPI时钟频率



  • 问题:高SPI时钟可能导致DMA传输速度跟不上。

  • 解决:尝试逐步降低SPI的SCK频率(如从50MHz降至25MHz),观察是否错误减少。

  • 配置方法:在SPI初始化代码中调整SPI_BaudRatePrescaler参数。




2. 检查DMA缓冲区配置



  • 问题:DMA缓冲区过小或未使用循环模式。

  • 解决

    • 增大接收和发送缓冲区(如从256字节增至512字节)。

    • 启用DMA循环模式(Circular Mode),避免缓冲区溢出。


  • 配置示例
    hdma_rx.Init.PeriphRequest = BDMA_REQUEST_SPI6_RX;
    hdma_rx.Init.Mode = DMA_CIRCULAR;  // 循环模式
    hdma_tx.Init.Mode = DMA_CIRCULAR;




3. 确保中断优先级和错误处理



  • 问题:DMA或SPI中断被阻塞,导致数据未及时处理。

  • 解决

    • 提升SPI和BDMA相关中断的优先级(如使用HAL_NVIC_SetPriority)。

    • 在SPI错误中断回调函数中清除错误标志并复位SPI。


  • 代码片段
    void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi) {
    if (hspi->Instance == SPI6) {
      __HAL_SPI_CLEAR_UDRFLAG(hspi);  // 清除UDR标志
      __HAL_SPI_CLEAR_OVRFLAG(hspi);  // 清除OVR标志
      HAL_SPI_DeInit(hspi);
      HAL_SPI_Init(hspi);
      // 重新启动DMA传输
    }
    }




4. 配置DMA双缓冲(Double Buffer)



  • 问题:单缓冲区切换时导致数据覆盖。

  • 解决:启用DMA双缓冲模式,交替处理数据。

  • 配置示例
    hdma_rx.Init.DoubleBufferMode = ENABLE;
    hdma_rx.Init.MemoryBurst = DMA_MBURST_INC4;
    HAL_DMAEx_MultiBufferStart_IT(&hdma_rx, (uint32_t)&SPI6->RXDR, rx_buf0, rx_buf1, BUFFER_SIZE);




5. 缓存一致性处理(Cache Coherency)



  • 问题:H7的Cache导致DMA访问内存数据不一致。

  • 解决

    • 使用SCB_CleanDCache_by_AddrSCB_InvalidateDCache_by_Addr维护缓存。

    • 通过MPU配置DMA缓冲区内存为非缓存(Non-Cacheable)或写透(Write-Through)。


  • 代码示例
    // 发送前清理发送缓冲区缓存
    SCB_CleanDCache_by_Addr(tx_buffer, BUFFER_SIZE);
    // 接收后无效化接收缓冲区缓存
    SCB_InvalidateDCache_by_Addr(rx_buffer, BUFFER_SIZE);




6. 检查DMA触发和SPI使能顺序



  • 问题:DMA未启动时SPI已开始传输。

  • 解决:确保先启动DMA,再使能SPI传输。

  • 正确顺序
    HAL_DMA_Start_IT(&hdma_rx, (uint32_t)&SPI6->RXDR, (uint32_t)rx_buf, BUFFER_SIZE);
    HAL_DMA_Start_IT(&hdma_tx, (uint32_t)tx_buf, (uint32_t)&SPI6->TXDR, BUFFER_SIZE);
    HAL_SPI_TransmitReceive_DMA(&hspi6, tx_buf, rx_buf, BUFFER_SIZE);




7. 验证硬件信号完整性



  • 问题:SCK/MISO/MOSI信号受干扰导致通信错误。

  • 解决

    • 检查PCB走线是否匹配SPI高速信号要求(阻抗、长度)。

    • 使用示波器监测SCK和数据线波形,确认无振铃或过冲。





8. 使用STM32CubeMonitor调试



  • 操作:通过实时监控SPI6和BDMA寄存器(如SPI_SRBDMA_CxCR),分析错误触发时的状态。




总结


通过调整SPI/DMA配置、优化中断处理、确保缓存一致性,并验证硬件信号,可有效解决UDR和OVR错误。若问题仍存在,建议逐步简化代码(如禁用其他外设),定位冲突源。

举报

杨玲

2025-3-15 16:36:12
这就看你程序逻辑了。


UDR表示发生了underrun错误,发生在从模式的发送阶段的发送FIFO为空时。


确保在主机启动时钟之前,TxFIFO中已经有足够的数据。


在TxFIFO为空时,不要清除UDR标志。确保在清除UDR标志之前,TxFIFO中已经有数据。


至于OVR错误,那就比较常见,发生在接收时前面数据没取走又来新数据了。尽量保证数据提取的即使性。


合理安排代码中的中断,不必要的中断就别开了,比方DMA传输半完成中断,中断处理代码力求简洁。
举报

王思敏

2025-3-15 16:36:17
可以屏蔽其他代码试试,或者固定和简化通讯数据。


看看是配置上的问题还是软件架构上的问题。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分