DMA工作原理:传输流程、请求响应与传输模式

大家好,我是你们的芯片架构设计课讲师。今天我们来聊聊DMA的核心工作原理。说实话,DMA这玩意儿在芯片设计里太常见了,但很多人对它的理解停留在「能搬数据」这个层面。我当年刚入行时也踩过不少坑,今天就把这些经验分享给你们。

一、DMA传输的基本流程

DMA传输,说白了就是让数据绕过CPU,直接在内存和外设之间搬运。为什么要这么做?你想想看,如果每次数据搬运都要CPU参与,那CPU就别干别的了,光忙着搬砖了。

一个完整的DMA传输流程,我习惯把它拆成三个阶段:

  1. 初始化阶段:CPU配置DMA控制器,告诉它「从哪搬、搬到哪、搬多少」
  2. 传输阶段:DMA控制器接管总线,开始搬运数据
  3. 结束阶段:传输完成,DMA通知CPU「活干完了」

我在项目中遇到过这样一个场景:某次做视频采集卡,数据量特别大。如果每帧图像都让CPU去搬,帧率直接掉到个位数。后来改用DMA,CPU只负责配置一次,剩下的全交给DMA,帧率瞬间就上去了。

核心要点:DMA传输的本质是「CPU授权,DMA执行」。CPU只做决策,不参与执行。

二、DMA请求与响应机制

DMA怎么知道什么时候该干活?这就涉及到请求与响应机制了。我画了一张流程图,帮大家理清这个逻辑:

外设 DMA控制器 CPU 内存 ① 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