4. DMA控制器基础:嵌入式SoC中DMA引擎的工作原理、通道与描述符
在音频驱动中,DMA(Direct Memory Access)是连接外设(如I2S控制器)与系统内存之间的高速数据通道。理解DMA控制器的工作原理、通道分配机制以及描述符链管理,是优化音频中断处理、降低CPU负载的前提。
4.1 DMA引擎核心架构
嵌入式SoC中的DMA引擎通常集成在系统总线矩阵中,具备多个独立通道,每个通道可配置为不同的传输模式。其核心工作流程如下:
- 触发源:外设(如I2S TX FIFO空、RX FIFO满)发出DMA请求。
- 通道仲裁:DMA控制器根据优先级选择待处理的通道。
- 描述符解析:从内存中读取当前描述符,获取源地址、目的地址、传输宽度、传输计数。
- 总线传输:通过系统总线执行一次或多次突发传输(burst transfer)。
- 中断/完成:传输完成后更新描述符状态,触发传输完成中断或自动加载下一个描述符。
关键指标: DMA传输延迟通常由总线仲裁时间 + 描述符加载时间 + 突发传输时间组成。在音频场景中,单次DMA传输延迟应小于一个采样周期(例如48kHz采样率下约20.8μs)。
4.2 DMA通道与优先级管理
每个DMA通道对应一个独立的传输上下文,包含源地址、目的地址、传输计数、传输宽度、突发大小等寄存器。通道的优先级决定了多个请求同时到达时的服务顺序。
| 通道属性 | 典型配置 | 音频场景说明 |
|---|---|---|
| 通道编号 | 0 ~ 7(8通道) | 通常I2S TX占用通道0,I2S RX占用通道1 |
| 优先级 | 固定优先级 / 轮转优先级 | 音频TX通道建议设为高优先级,防止音频断流 |
| 传输宽度 | 8/16/32位 | 音频数据通常为16位或32位 |
| 突发大小 | 1/4/8/16次传输 | 建议4或8,平衡总线占用与延迟 |
| 传输方向 | 内存→外设 / 外设→内存 | 播放:内存→I2S TX;录音:I2S RX→内存 |
工程建议: 在音频驱动初始化时,将I2S TX通道优先级设置为最高(如通道0固定优先级),RX通道设置为次高。避免在音频传输过程中动态调整优先级,否则可能导致DMA仲裁抖动。
4.3 描述符链(Descriptor Chain)机制
描述符是DMA传输的“指令卡片”,每个描述符定义了一次传输的所有参数。描述符链将多个描述符以链表形式组织,DMA控制器在完成当前描述符后自动加载下一个,实现连续传输而无需CPU干预。
描述符的典型结构如下:
struct dma_descriptor {
uint32_t src_addr; // 源地址(内存或外设地址)
uint32_t dst_addr; // 目的地址
uint32_t transfer_size; // 传输字节数
uint32_t ctrl; // 控制字:宽度、突发大小、中断使能
uint32_t next_desc; // 下一个描述符的物理地址(链表指针)
uint32_t status; // 状态字:完成标志、错误标志
};
描述符链的优势: 通过环形描述符链(ring buffer),DMA可以自动循环播放/录音,CPU只需在缓冲区边界处处理半满/全满中断,大幅降低中断频率。
4.4 描述符链在音频驱动中的典型配置
在音频驱动中,描述符链通常配置为双缓冲(ping-pong buffer)或多缓冲环。以双缓冲为例:
- 描述符0:指向缓冲区A,传输完成后触发半满中断。
- 描述符1:指向缓冲区B,传输完成后触发全满中断。
- 回链:描述符1的next指针指向描述符0,形成循环。
CPU在中断服务程序中处理已完成的缓冲区,同时DMA自动切换到另一个缓冲区,实现无间隙传输。
常见陷阱: 描述符链必须位于非缓存(non-cacheable)内存区域,或使用DMA一致性内存分配(如dma_alloc_coherent)。否则,CPU缓存与DMA之间的数据一致性会导致传输错误。
4.5 描述符链与中断频率的关系
描述符链的长度直接影响中断频率。假设音频采样率为48kHz,采样精度为16位,双声道:
| 描述符链长度 | 每个描述符传输字节数 | 中断频率 | CPU负载 |
|---|---|---|---|
| 2(双缓冲) | 4KB | ~11.7 kHz | 高 |
| 4 | 8KB | ~5.9 kHz | 中 |
| 8 | 16KB | ~2.9 kHz | 低 |
| 16 | 32KB | ~1.5 kHz | 极低 |
优化策略: 在音频延迟要求不苛刻的场景(如音乐播放),使用8~16个描述符的环形链,将中断频率降低到2~3kHz,显著减少CPU上下文切换开销。对于低延迟场景(如VoIP),使用2~4个描述符,牺牲部分CPU负载换取更低的响应延迟。