最近在调试一个基于 FPGA 和 ARM 的异构系统时,遇到了一个看似简单却让人困惑的问题:数据通过 DMA 从 PL 侧搬运到 PS 侧的内存后,PS 侧的应用程序读取到的数据偶尔会出错。硬件同事信誓旦旦地说 AXI 总线上的时序没问题,软件同事则坚持认为 DMA 配置和中断处理逻辑是标准的。问题卡在这里,排查一度陷入僵局。后来,我们把目光从“DMA 有没有搬完”和“AXI 时序对不对”这两个孤立的问题上移开,聚焦在它们之间的握手与协作上,才最终定位到问题根源——不是谁错了,而是两者协作时的“认知”出现了偏差。这个经历让我意识到,对于很多嵌入式开发者来说, DMA 和 AXI 这两个概念分开看都懂,但一旦组合成“AXI DMA”,其背后的数据流、控制流和同步机制,就成了一片需要仔细厘清的模糊地带。
“DMA 02AXI-02”这个标题,初看像某个内部项目代号或测试用例编号,但它精准地指向了问题的核心:基于 AXI 总线的 DMA 传输(02很可能指代一种特定模式或版本)。在 Zynq、MPSoC 或各类集成 AXI 总线的 SoC 中,AXI DMA IP 核是连接可编程逻辑(PL)与处理系统(PS)进行高效数据搬移的关键桥梁。然而,很多教程和例程只教会我们如何配置寄存器、启动传输和处理中断,却很少深入解释: 数据究竟是如何穿过 AXI 总线这座“桥梁”的?DMA 控制器和 AXI 协议之间如何对话?为什么简单的“内存到外设”传输能正常工作,而复杂的“外设到内存”或链式传输就频频出问题?
理解 AXI DMA,绝不能停留在 HAL 库或标准库的函数调用层面。它本质上是一个硬件协议栈上的协作过程。本文将从一个系统视角,拆解 AXI DMA 的工作机制,特别是容易被忽略的“传输完成”判定、总线 Outstanding 能力对性能的隐形影响,以及如何构建一个稳健的、可复用的 DMA 驱动框架,而非仅仅复制粘贴一段“能跑”的代码。
1. 超越“搬运工”:理解 AXI DMA 在系统中的真实角色
当我们说“使用 DMA”时,潜意识里往往把它想象成一个单纯的、高效的“数据搬运工”。CPU 下达指令:“把这里的数据搬到那里”,然后 DMA 默默工作,完成后发个中断通知 CPU。这个模型对于简单的内存到内存(Memory-to-Memory)DMA 是足够的。但一旦引入 AXI 总线,特别是连接异构单元(如 PL 的 IP 核与 PS 的 DDR)时,DMA 的角色就复杂多了。
1.1 AXI DMA:不止是搬运,更是协议翻译与流量控制
在 AXI 体系结构中,DMA 控制器(如 Xilinx 的 AXI DMA IP 或 ARM 的 PL330)本身是一个 AXI Master 设备。它的核心功能之一是进行 协议转换 和 流量管理 。
- 从“寄存器指令”到“总线事务”的翻译 :CPU 通过 AXI-Lite 或 APB 这类轻量总线配置 DMA 的控制寄存器(如源地址、目标地址、长度)。DMA 控制器内部将这些配置信息,转换为一组或多组符合 AXI 协议规范的读/写事务(AXI Read/Write Transactions)。例如,一次大块数据搬运,可能被拆分成多个符合 AXI 突发(Burst)传输规则的小事务。
- 管理多个未完成事务(Outstanding) :这是 AXI 总线提升性能的关键机制,也是很多问题的来源。Outstanding 能力允许一个 Master 在未收到前一个事务的响应时,就发出下一个事务的地址和控制信息。AXI DMA 控制器通常支持一定数量的 Outstanding 事务。如果配置不当(例如在 FPGA 逻辑中未正确实现或连接 Slave 的响应能力不足),可能导致总线死锁或数据乱序,尽管每个单一事务的时序都正确。
- 连接不同的时钟域和内存空间 :DMA 经常需要跨越不同的时钟域(如 PL 侧逻辑时钟和 PS 侧 AXI 总线时钟),并在不同的内存映射区域间移动数据(如 PL 侧的 BRAM、PS 侧的 DDR、外设寄存器等)。它需要处理时钟同步和地址映射。
因此,看待 AXI DMA,首先要将其视为一个 智能的、可编程的 AXI 事务生成器与管理器 ,而不仅仅是一个傻快的搬运通道。
1.2 同步的陷阱:“发送完成”中断到底意味着什么?
搜索热词中“串口dma发送完成中断”和“dma传输最后一个字节后 怎么判断串口已发送完成?”这两个问题,非常典型地揭示了 DMA 使用中的一个核心困惑点: DMA 传输完成(Transfer Complete)中断触发,是否等同于数据已真正到达目的地并被成功处理?
答案是否定的。这中间存在一个关键的“时间差”和“责


2093

被折叠的 条评论
为什么被折叠?



