4. DMA传输模式:单次、块、突发、循环的特点与选择
DMA传输模式,说白了就是DMA控制器搬运数据时采用的几种不同“节奏”。选对了,系统性能蹭蹭往上涨;选错了,CPU反而会被频繁打断,得不偿失。我刚开始接触DMA时,就吃过这个亏——图省事全用单次模式,结果高负载下系统响应一塌糊涂。
这四种模式各有各的脾气。咱们一个一个来看。
4.1 单次传输模式
单次模式是最基础的玩法。每次DMA请求,只传输一个数据单元(比如一个字节或一个字),然后释放总线。下次请求再来一个,如此反复。
核心特征:
- 每次传输后释放总线控制权
- 传输粒度最小,一个请求对应一个数据单元
- 对总线占用时间最短
我在一个低速传感器项目中用过这种模式。传感器每秒只产生几十个字节,用单次模式完全够用,而且不会影响其他外设的总线访问。说白了,它适合那种数据量小、传输不频繁的场景。
| 特性 | 说明 |
|---|---|
| 总线占用 | 极短,每次传输后立即释放 |
| 传输效率 | 低,每次都需要重新仲裁总线 |
| 适用场景 | 低速外设、数据量小、对实时性要求不高 |
| CPU干预 | 每次传输都可能产生中断 |
注意:单次模式虽然对总线友好,但频繁的总线仲裁会带来额外开销。如果数据量稍大,效率会明显下降。我曾经在一个项目中用单次模式传输几百字节的数据,结果DMA的中断频率高到CPU几乎没法干别的活。
4.2 块传输模式
块传输模式就聪明多了。它一次请求,连续传输一整块数据,传输完才释放总线。块的大小可以配置,比如64字节、128字节或者更多。
你想想看,同样是传1024字节,单次要请求1024次总线,块模式可能只需要请求16次(如果块大小是64字节)。效率差距一目了然。
核心特征:
- 一次请求传输一个完整的数据块
- 块大小可配置,通常为2的幂次
- 传输期间独占总线
我个人习惯在音频数据流处理中用块模式。比如I2S接口采集音频,每次触发传输一个音频帧(比如256个采样点),块模式正好匹配这种需求。不过要注意,块模式会长时间占用总线,如果系统中有其他高优先级外设,可能会造成延迟。
| 特性 | 说明 |
|---|---|
| 总线占用 | 较长,传输完整块后才释放 |
| 传输效率 | 高,减少了总线仲裁次数 |
| 适用场景 | 中高速外设、数据流传输、音频/视频处理 |
| CPU干预 | 每块传输完成后产生中断 |
经验之谈:块大小的选择有讲究。块太大,总线被占太久,其他外设可能饿死;块太小,又体现不出块模式的优势。我一般从系统允许的最大延迟反推块大小,再留20%的余量。
4.3 突发传输模式
突发模式是块模式的“升级版”。它允许DMA在获得总线控制权后,连续传输多个数据单元,但传输次数是固定的,由硬件寄存器配置。常见的突发长度有4、8、16次等。
突发模式和块模式有什么区别?嗯,这里要注意:块模式传输的是逻辑上完整的一块数据,而突发模式强调的是连续传输的次数。突发模式更底层,它关心的是总线协议层面的传输行为。
核心特征:
- 固定长度的连续传输序列
- 突发长度由硬件寄存器配置
- 适合高性能总线(如AHB、AXI)
我记得在调试一个高速ADC采集项目时,用了突发模式配合AXI总线。ADC采样率高达100Msps,数据量巨大。突发模式让DMA能以最高效率搬移数据,总线利用率接近饱和。但代价是,CPU和低优先级外设几乎抢不到总线。
| 特性 | 说明 |
|---|---|
| 总线占用 | 取决于突发长度,通常较短但密集 |
| 传输效率 | 极高,充分利用总线带宽 |
| 适用场景 | 高速外设、大数据量、高性能总线系统 |
| CPU干预 | 整个突发传输完成后产生中断 |
避坑指南:我曾经在一个项目中把突发长度设得太大,结果DMA连续传输时,CPU连中断都响应不了。后来把突发长度从16降到8,问题就解决了。突发长度不是越大越好,得看系统的实时性要求。
4.4 循环传输模式
循环模式,也叫环形缓冲区模式。它让DMA在固定的内存区域里循环传输数据,传完一圈自动从头开始。这种模式特别适合数据流处理,比如音频播放、网络数据包收发。
说白了,循环模式就是给DMA画了个圈,让它一直在里面转。你不需要每次传输完都重新配置DMA,省了不少事。
核心特征:
- 传输地址自动回绕到起始地址
- 无需软件干预即可持续传输
- 通常配合双缓冲或环形缓冲区使用
我做过一个音频播放器项目,用循环模式配合双缓冲。DMA在缓冲区A和B之间循环填充数据,CPU只需要在缓冲区满时处理数据。这种设计让音频播放非常流畅,几乎没有卡顿。
| 特性 | 说明 |
|---|---|
| 总线占用 | 持续占用,但每次传输量可控 |
| 传输效率 | 高,无需重复配置DMA |
| 适用场景 | 流式数据、音频/视频、网络数据包 |
| CPU干预 | 仅在缓冲区半满或全满时产生中断 |
实用技巧:循环模式一定要配合中断使用。我习惯设置两个中断点:缓冲区半满和全满。半满时CPU开始处理前半部分数据,全满时处理后半部分。这样CPU和DMA可以流水线作业,效率最高。
4.5 四种模式对比与选择
四种模式各有千秋,选哪个得看具体需求。我整理了一张对比表,方便你快速决策。
| 模式 | 总线占用 | 传输效率 | CPU干预 | 典型场景 |
|---|---|---|---|---|
| 单次模式 | 极短 | 低 | 频繁 | 低速外设、小数据量 |
| 块模式 | 较长 | 高 | 中等 | 音频流、数据块传输 |
| 突发模式 | 短而密集 | 极高 | 较少 | 高速ADC、高性能总线 |
| 循环模式 | 持续 | 高 | 最少 | 流式数据、环形缓冲区 |
怎么选?我一般按这个思路来:
- 数据量小、外设慢 → 单次模式,简单可靠
- 数据量中等、有固定数据块 → 块模式,效率与实时性平衡
- 数据量大、总线带宽高 → 突发模式,榨干总线性能
- 持续流式数据 → 循环模式,省心省力
最后提醒一句:实际项目中,DMA控制器可能支持多种模式组合。比如突发模式配合循环模式,或者块模式配合单次模式。别被“只能选一种”的想法限制住,多看看芯片手册,灵活运用才是王道。