1. DMA 基础概念
直接存储器访问(Direct Memory Access, DMA)是嵌入式系统中解放 CPU 的关键硬件机制。在 Linux 驱动开发中,理解 DMA 的工作原理、控制器架构和传输类型,是正确实现高性能数据通路的前提。本节从硬件原理出发,逐步建立 DMA 的完整知识框架。
1.1 DMA 工作原理
传统 PIO(Programmed I/O)模式下,CPU 必须逐字搬运外设数据,导致 CPU 被完全占用。DMA 允许外设与内存之间直接交换数据,CPU 只需发起传输请求,后续搬运由 DMA 控制器独立完成。
核心收益:CPU 从数据搬运中解放,可并行处理其他任务,系统吞吐量提升 5~10 倍(典型场景)。
一次完整的 DMA 传输包含以下 5 个阶段:
- CPU 配置 DMA 控制器:设置源地址、目的地址、传输长度、传输方向、触发源等参数。
- CPU 启动传输:写 DMA 控制器的使能寄存器,DMA 开始工作。
- DMA 控制器接管总线:向总线仲裁器请求总线控制权,获得授权后开始搬运。
- DMA 搬运数据:按配置的传输模式(单次/突发)从源读取、向目的写入。
- 传输完成中断:DMA 控制器向 CPU 发送中断,通知传输结束。
1.2 DMA 控制器架构
现代 SoC 中的 DMA 控制器通常采用多通道架构,每个通道独立管理一条数据流。以 ARM PrimeCell PL080 为例,其内部结构包含以下关键模块:
| 模块 | 功能描述 | 驱动关注点 | ||
|---|---|---|---|---|
| 通道控制器 | 管理 8 个独立 DMA 通道,每个通道有独立的源/目的地址寄存器 | 通道分配与复用策略 | ||
| 总线接口单元 | 连接 AHB/AXI 总线,处理总线仲裁与突发传输 | 总线宽度对齐(32/64/128-bit) | ||
| FIFO 缓冲 | 深度 4~16 字的暂存区,用于源/目的速率匹配 | FIFO 阈值配置影响传输效率 | ||
| 中断控制器 | 汇总各通道完成/错误中断,向 GIC 上报 | 中断处理函数注册与清除 | ||
| 链接列表引擎 | 支持硬件链表(LLI),自动加载下一组传输描述符 | 链表描述符内存对齐要求 |
| 传输类型 | 数据流向 | 典型场景 | 硬件要求 | Cache 一致性影响 |
|---|---|---|---|---|
| 内存到内存 | 内存 → 内存 | 帧缓冲拷贝、数据搬移、内存校验 | 源/目的地址必须对齐到传输宽度 | 需 CPU 手动刷新 cache(非一致性总线) |
| 内存到外设 | 内存 → 外设 FIFO | LCD 显示刷新、音频播放、网络 TX | 外设地址固定,内存缓冲区需连续 | 写操作:传输前 clean cache |
| 外设到内存 | 外设 FIFO → 内存 | 摄像头采集、音频录音、网络 RX | 外设触发信号(硬件请求线) | 读操作:传输后 invalidate cache |
| 模式 | 传输粒度 | 总线占用 | 适用场景 | 延迟特性 |
|---|---|---|---|---|
| 单次传输 | 1 字/次 | 低(每次释放总线) | 低速外设(UART、I2C) | 高(频繁仲裁) |
| 突发传输 | 4/8/16 字/次 | 高(持续占用总线) | 高速外设(LCD、Camera) | 低(批量搬运) |
| 链表传输 | 多段描述符 | 按需 | 分散/聚集 I/O(网络、存储) | 中(硬件自动加载) |
| 循环传输 | 自动回绕 | 持续 | 音频环形缓冲区 | 极低(无中断开销) |