4. DMA基础概念:DMA控制器、DMA传输模式、DMA与CPU协同
直接存储器访问(Direct Memory Access, DMA)是嵌入式系统中实现高性能数据传输的核心机制。它允许外设与存储器之间直接交换数据,而无需CPU逐字节干预,从而大幅降低CPU负载并提升系统吞吐量。本章将深入剖析DMA控制器的硬件结构、传输模式以及DMA与CPU的协同工作模型,为后续理解DMA映射与SMMU配置奠定基础。
4.1 DMA控制器架构与核心组件
DMA控制器(DMAC)是一个独立的总线主控设备,能够发起总线事务并控制数据流。典型的DMA控制器包含以下关键模块:
| 组件 | 功能描述 | 硬件实现要点 |
|---|---|---|
| 通道控制器 | 管理多个独立DMA通道,每个通道对应一个传输上下文 | 通道数通常为4~32,支持优先级仲裁 |
| 源地址寄存器 | 存储数据源地址(外设寄存器或内存地址) | 支持地址递增、递减或固定模式 |
| 目的地址寄存器 | 存储数据目的地址 | 与源地址寄存器对称设计 |
| 传输计数寄存器 | 记录待传输的数据单元数量 | 递减至0时触发传输完成中断 |
| 控制状态寄存器 | 配置传输模式、数据宽度、突发大小等参数 | 包含启动/暂停/中止控制位 |
| 总线接口单元 | 实现与系统总线(AHB/AXI/CHI)的协议握手 | 支持单次传输与突发传输 |
dmaengine框架进行抽象。驱动开发者需要关注通道分配、描述符链管理以及回调机制,而非直接操作硬件寄存器。
4.2 DMA传输模式详解
DMA控制器支持多种传输模式,以适应不同的应用场景。理解这些模式是正确配置DMA映射的前提。
4.2.1 单次传输模式
每次DMA请求只传输一个数据单元(字节、半字或字),然后释放总线。适用于低速外设或数据量较小的场景。
4.2.2 突发传输模式
一次DMA请求连续传输多个数据单元(突发长度可配置,如4、8、16次传输)。突发传输能显著提高总线利用率,但会占用总线较长时间,可能影响其他总线主控的延迟。
4.2.3 循环传输模式
传输完成后自动重置地址和计数寄存器,实现连续循环传输。常用于音频流、ADC连续采样等需要持续数据流的场景。
4.2.4 描述符链模式
通过链表组织多个传输描述符,每个描述符定义一次传输的源地址、目的地址、长度和配置。DMA控制器自动遍历链表,完成所有传输后产生中断。这是Linux内核dmaengine框架的核心传输模式。
| 模式 | 总线占用 | CPU干预 | 适用场景 |
|---|---|---|---|
| 单次传输 | 低 | 每次传输后需重新配置 | UART、I2C等低速外设 |
| 突发传输 | 高 | 一次配置完成多次传输 | 高速存储、网络控制器 |
| 循环传输 | 持续 | 仅初始配置 | 音频、传感器数据流 |
| 描述符链 | 可配置 | 批量提交,中断少 | 复杂DMA操作、多缓冲区 |
4.3 DMA与CPU协同工作模型
DMA与CPU的协同是系统性能优化的关键。两者通过共享系统总线访问内存,必须建立清晰的同步与互斥机制。
4.3.1 协同工作流程
- CPU配置DMA:设置源地址、目的地址、传输长度、传输模式,并启动DMA。
- DMA自主传输:DMA控制器接管总线控制权,按配置完成数据传输。CPU可继续执行其他任务。
- 传输完成通知:DMA通过中断或轮询标志通知CPU传输结束。
- CPU处理数据:CPU检查数据一致性(Cache刷新/无效化),处理传输结果。
4.3.2 缓存一致性问题
在带Cache的系统中,DMA直接访问物理内存,而CPU可能通过Cache访问同一内存区域。这会导致数据不一致:
- DMA写入内存,CPU读取:CPU Cache中可能包含旧数据,需执行Cache无效化操作。
- CPU写入内存,DMA读取:CPU写入的数据可能仍在Cache中未写回内存,需执行Cache写回操作。
dma_map_single()/dma_unmap_single()等API自动处理Cache维护,而非手动操作。
4.3.3 同步机制
DMA与CPU的同步通常通过以下方式实现:
| 同步方式 | 延迟 | CPU开销 | 适用场景 |
|---|---|---|---|
| 中断 | 中等(中断响应延迟) | 低(仅处理中断时) | 大多数DMA传输 |
| 轮询状态寄存器 | 低(立即检测) | 高(持续占用CPU) | 短时、高实时性传输 |
| DMA完成回调 | 取决于调度 | 低(内核上下文处理) | Linux dmaengine框架 |
4.4 DMA传输流程SVG架构图
下图展示了从CPU配置DMA到传输完成的完整流程,以及DMA与CPU、内存、外设之间的数据通路:
4.5 DMA传输模式选择策略
在实际嵌入式系统中,选择合适的DMA传输模式需要综合考虑以下因素:
- 数据量大小:小数据量(< 64字节)适合单次传输,大数据量(> 1KB)适合突发传输。
- 实时性要求:高实时性场景应避免长时间突发传输阻塞总线。
- 外设特性:FIFO深度小的外设需使用单次传输防止溢出;支持流控制的外设可配合突发传输。
- 系统负载:多DMA通道并发时,需合理分配优先级和带宽。
dma-burst-size和dma-maxburst属性指定突发长度。驱动中调用dmaengine_slave_config()设置src_addr_width、dst_addr_width和src_maxburst等参数。