DMA工作原理:传输流程、请求响应与传输模式
大家好,我是你们的芯片架构设计课讲师。今天我们来聊聊DMA的核心工作原理。说实话,DMA这玩意儿在芯片设计里太常见了,但很多人对它的理解停留在「能搬数据」这个层面。我当年刚入行时也踩过不少坑,今天就把这些经验分享给你们。
一、DMA传输的基本流程
DMA传输,说白了就是让数据绕过CPU,直接在内存和外设之间搬运。为什么要这么做?你想想看,如果每次数据搬运都要CPU参与,那CPU就别干别的了,光忙着搬砖了。
一个完整的DMA传输流程,我习惯把它拆成三个阶段:
- 初始化阶段:CPU配置DMA控制器,告诉它「从哪搬、搬到哪、搬多少」
- 传输阶段:DMA控制器接管总线,开始搬运数据
- 结束阶段:传输完成,DMA通知CPU「活干完了」
我在项目中遇到过这样一个场景:某次做视频采集卡,数据量特别大。如果每帧图像都让CPU去搬,帧率直接掉到个位数。后来改用DMA,CPU只负责配置一次,剩下的全交给DMA,帧率瞬间就上去了。
核心要点:DMA传输的本质是「CPU授权,DMA执行」。CPU只做决策,不参与执行。
二、DMA请求与响应机制
DMA怎么知道什么时候该干活?这就涉及到请求与响应机制了。我画了一张流程图,帮大家理清这个逻辑:
这个流程其实很直观:
- 第一步:外设准备好了数据,向DMA发请求信号
- 第二步:DMA向CPU请求总线控制权,CPU授权
- 第三步:DMA开始搬运数据,从外设到内存(或反过来)
- 第四步:搬运完成,DMA发中断通知CPU
个人经验:我曾经在一个项目中,DMA请求信号没做同步处理,结果在跨时钟域时出现了毛刺,导致DMA误触发。后来加了个两级同步器才解决。嗯,跨时钟域问题一定要重视。
三、DMA传输模式详解
DMA有三种常见的传输模式:单次传输、突发传输和循环传输。每种模式都有自己的适用场景,我给大家逐一分析。
1. 单次传输模式
单次传输,就是每次DMA请求只传输一个数据单元。这个模式最简单,但效率也最低。
// 单次传输配置示例
DMA_CTRL = 0x01; // 使能DMA
DMA_SRC = 0x4000; // 源地址
DMA_DST = 0x5000; // 目的地址
DMA_CNT = 1; // 传输1个数据单元
DMA_START = 1; // 启动传输
什么时候用单次传输?我建议在数据量小、实时性要求高的场景用。比如按键扫描,每次只传一个字节,用单次模式就够了。
2. 突发传输模式
突发传输就厉害了。它一次请求可以传输多个数据单元,效率高得多。我习惯叫它「批量搬运」。
// 突发传输配置示例
DMA_CTRL = 0x03; // 使能DMA + 突发模式
DMA_SRC = 0x4000; // 源地址
DMA_DST = 0x5000; // 目的地址
DMA_CNT = 256; // 传输256个数据单元
DMA_BURST = 16; // 每次突发16个
DMA_START = 1; // 启动传输
突发传输的关键参数是突发长度。我见过很多新手把突发长度设得特别大,结果总线被长时间占用,其他设备都卡死了。这里有个经验值:突发长度一般设为总线宽度的整数倍,比如32位总线,突发长度设4或8比较合适。
避坑指南:我曾经在一个项目中,把突发长度设成了64,结果DMA一启动,其他外设全都不响应了。后来查了总线协议才发现,突发传输会独占总线,太长会影响系统实时性。建议突发长度不要超过16。
3. 循环传输模式
循环传输,也叫自动重载模式。它会在传输完成后自动重新加载配置,继续下一轮传输。这个模式特别适合音频、视频等连续数据流场景。
// 循环传输配置示例
DMA_CTRL = 0x05; // 使能DMA + 循环模式
DMA_SRC = 0x4000; // 源地址
DMA_DST = 0x5000; // 目的地址
DMA_CNT = 1024; // 传输1024个数据单元
DMA_LOOP = 1; // 使能循环
DMA_START = 1; // 启动传输
循环传输有个坑要注意:地址回绕。如果源地址和目的地址是线性递增的,循环传输结束后地址会回到初始值。但如果你用的是链表或环形缓冲区,地址管理就要自己处理了。
四、三种模式对比
我把三种模式的特点整理成了表格,方便大家对比:
| 特性 | 单次传输 | 突发传输 | 循环传输 |
|---|---|---|---|
| 传输效率 | 低 | 高 | 高 |
| 总线占用 | 短 | 较长 | 持续 |
| 适用场景 | 小数据量、实时性高 | 大数据量、批量搬运 | 连续数据流 |
| 配置复杂度 | 简单 | 中等 | 中等 |
| 典型应用 | 按键、传感器 | 文件传输、图像采集 | 音频播放、视频显示 |
五、实际设计中的注意事项
讲完了理论,我再说几个实际设计中容易忽略的点:
- 地址对齐:DMA传输的源地址和目的地址最好对齐到总线宽度。比如32位总线,地址最好是4字节对齐。不对齐的话,性能会下降很多。
- 数据宽度匹配:源和目的的数据宽度要一致。我见过有人把8位的外设和32位的内存直接连,结果数据错位了。
- 中断处理:DMA传输完成中断要尽快处理,否则可能丢失后续数据。特别是在高速传输场景下。
我的习惯:在设计DMA控制器时,我会预留一个超时计数器。如果DMA请求后长时间没有响应,就触发超时中断。这个设计帮我排查过好几次总线死锁的问题。
好了,DMA的工作原理就讲到这里。记住一句话:DMA的核心价值在于「解放CPU」。你配置得越合理,CPU就越轻松,系统性能就越好。下次我们聊聊DMA的通道管理和优先级设计,那个更有意思。
公众号:蓝海资料掘金营,微信deep3321