STM32F7裸机UART非阻塞发送DMA数据缓存最优方案咨询
基于STM32F7 UART DMA无阻塞发送的最优实现思路
先对比你提到的两种方案的适用场景:
- 双DMA分段传输方案:无额外数据拷贝开销,CPU仅需完成两次DMA寄存器配置,耗时远低于memcpy操作,尤其适合单条调试数据长度大、发送频率高的场景,是性能优先的选择。仅需要在首次DMA传输完成中断中触发第二次传输,注意同步更新FIFO读指针即可。
- memcpy拷贝到连续缓存方案:逻辑简单,仅需发起一次DMA请求,无需维护分段传输状态,但memcpy开销随待发数据长度线性增长,且需要额外占用一块连续内存,仅适合单条数据普遍较短、RAM资源充足的场景。
业内性能最优的实现方案:启用DMA分散/聚集(Scatter-Gather)模式
STM32F7的DMA原生支持分散/聚集特性,不需要你手动分两次启动DMA,也无需额外数据拷贝:
- 提前在非缓存内存区域(或配置MPU关闭对应区域缓存,避免缓存一致性问题)定义两个DMA传输描述符
- 当遇到FIFO回卷场景时,配置第一个描述符的源地址为FIFO当前读指针、传输长度为FIFO尾部剩余字节数、目标地址为UART数据发送寄存器,配置为传输完成后自动加载下一个描述符
- 第二个描述符的源地址为FIFO起始地址、传输长度为回卷到头部的待发字节数,配置为传输完成后触发中断更新FIFO读指针
整个传输过程完全不需要CPU介入,性能比手动触发两次DMA还要高。
额外优化建议
- 可以做自适应策略:待发数据长度小于64字节时直接用
memcpy方案简化逻辑,长度大于等于64字节时用分散/聚集模式降低开销 - 环形FIFO大小配置为2的整数次幂,用位运算替代取模计算读写指针和剩余空间,进一步降低CPU运算开销
- 如果你的项目不需要兼容其他型号MCU,优先使用分散/聚集模式,否则手动分段触发DMA的方案兼容性最好。
内容的提问来源于stack exchange,提问作者Tim
相关产品推荐
相关产品推荐

