☰
DMA方式深度解析:从408考研到STM32实战
2026/9/28 1:02:21 网站建设 项目流程

1. 从一道45题说起:DMA到底在考什么

如果你正在准备计算机408统考,或者正在啃唐朔飞那本《计算机组成原理》,大概率会在“I/O设备与主机进行信息传送的控制方式”这一章卡住过。程序查询方式、程序中断方式、DMA方式,三种控制方式摆在一起,概念看着都懂,一到做题就分不清谁是谁。尤其是2024年那道45题,把DMA和中断的配合、周期挪用、传送单位这些点揉在一起考,很多人出来对答案才发现自己把“周期挪用”和“停止CPU访存”搞混了。

这篇内容就是围绕DMA方式这个核心知识点展开的。我会把DMA在408考试里的考查逻辑、在真实硬件(比如STM32、串口、SPI、ADC多通道采集)里的落地方式,以及唐朔飞、白中英教材里那些容易被忽略的细节,全部串起来讲清楚。不管你是考研党、正在做计算机组成原理实验的本科生,还是写嵌入式驱动时天天跟DMA打交道但没系统梳理过原理的工程师,这篇都能让你对DMA有一套完整的认知框架。

先说结论性的判断:DMA的本质是让数据搬运这件事从CPU手里彻底剥离出去,由专门的硬件控制器在内存和I/O设备之间直接开通道。CPU只负责“发起”和“收尾”,中间搬多少、怎么搬,全交给DMA控制器。理解了这一点,后面所有的细节——周期挪用、传送单位、与中断的配合——都是这句话的展开。

2. DMA方式的核心设计逻辑与三种控制方式对比

2.1 为什么需要DMA:CPU不该当搬运工

要理解DMA为什么存在,得先看它替代的是什么。程序查询方式和程序中断方式,本质上都是CPU亲自参与数据搬运。程序查询方式是CPU不断轮询设备状态,设备准备好了就由CPU执行一条传送指令把数据从I/O接口读到CPU寄存器,再写到内存。程序中断方式稍微好一点,设备准备好后发中断,CPU暂停当前程序去处理,但数据传送这一步仍然是CPU用指令完成的。

问题就出在这里。假设你要从磁盘读1MB数据到内存,按每次传送4字节算,需要执行25万次传送指令。每次指令都要取指、译码、执行,CPU几乎被完全占用。对于高速设备(磁盘、网卡、显卡)来说,这种开销完全不可接受。CPU的时间应该花在计算上,而不是当搬运工。

DMA的思路很直接:既然搬运是机械重复的劳动,那就造一个专门的硬件——DMA控制器(DMAC)——来干这件事。CPU只需要告诉DMAC:从哪个设备读、写到内存哪个地址、传多少字节、传完后告诉我。剩下的活DMAC自己干,CPU该干嘛干嘛。

2.2 三种控制方式的关键差异对照

把三种方式放在一张表里对比,很多模糊的地方会立刻清晰:

对比维度程序查询方式程序中断方式DMA方式
数据传送控制者CPUCPUDMA控制器
CPU参与程度全程参与,不断轮询数据传送时参与仅初始化和收尾
传送单位字(或字节)字(或字节)数据块
中断需求不需要每次传送都中断传送结束后中断一次
适用设备低速设备中低速设备高速设备
数据通路经CPU经CPU不经过CPU,直接内存-设备
对CPU的干扰完全占用频繁打断仅在存取周期层面借用

这张表里最关键的一行是“传送单位”。程序查询和中断都是以字为单位,每传一个字都要CPU介入一次;DMA是以数据块为单位,一整块数据搬完才通知CPU。这个差异直接决定了三者的效率量级。

2.3 DMA控制器的内部结构拆解

DMAC不是个黑盒,它内部有几个关键寄存器,理解了它们就理解了DMA的工作流程:

  • 内存地址寄存器(AR):存放当前要读写的内存地址,每传送一个数据后自动加1(或减1)。
  • 字计数器(WC):记录还剩多少数据没传,每传送一个减1,减到0时表示传送完成。
  • 设备地址寄存器(DAR):存放I/O设备的地址,用来选中要通信的设备。
  • 控制与状态寄存器:存放传送方向(读/写)、传送模式、中断使能等控制位,以及传送完成、出错等状态位。

CPU初始化DMA时,就是往这几个寄存器里写值。比如要从磁盘读4KB到内存0x2000开始的位置,CPU就设置AR=0x2000,WC=4096(假设按字节计),DAR=磁盘接口地址,控制寄存器设为“读”方向、块传送模式、允许中断。设置完,CPU发一条“启动DMA”命令,然后就可以去执行别的程序了。

注意:不同教材对寄存器的命名略有差异,唐朔飞教材里常叫“主存地址寄存器”“传送长度计数器”,白中英教材里叫“内存地址计数器”“字计数器”,考试时看清题目用的是哪套术语。

3. DMA的三种传送方式与总线占用机制

3.1 停止CPU访存:最简单但最浪费

停止CPU访存方式,顾名思义,DMA传送期间CPU完全停止访问内存。DMAC向CPU发一个“总线请求”信号,CPU响应后让出总线控制权,DMAC独占内存总线进行数据传送,传完再把总线还给CPU。

这种方式的好处是控制简单,DMAC不需要复杂的时序逻辑。坏处也很明显:如果传送的数据块很大,CPU会被长时间“冻结”,内存的利用率也低——因为DMAC传送时可能有很多空闲周期,但CPU没法利用。

这种方式适合数据块不大、对CPU实时性要求不高的场景。考试里如果题目说“DMA传送期间CPU不能访存”,基本就是在描述这种方式。

3.2 周期挪用:408最爱考的重点

周期挪用(也叫周期窃取)是DMA最常考的方式,也是2024年45题涉及的核心概念。它的思路是:DMAC不独占总线,而是在CPU不使用内存总线的时候,“偷”一个存取周期来传送一个数据。具体又分两种情况:

第一种是CPU正在访存,DMAC等CPU访存结束后再借用下一个周期。这种情况下DMA传送对CPU几乎没有影响,只是偶尔让CPU的指令执行慢一个周期。

第二种是CPU和DMAC同时请求访存,这时DMAC优先。因为I/O设备的数据传输有实时性要求,如果数据没及时取走可能会丢失(比如磁盘旋转过去就错过了),而CPU晚一个周期执行影响不大。

周期挪用的精髓在于“挪用”二字——DMAC借用的只是一个存取周期,不是整个总线控制权。每传送一个数据,就挪用一次。传送一个数据块,就挪用N次。这种方式下CPU和DMA交替使用内存,效率最高,也是实际硬件中最常用的方式。

实操心得:STM32里的DMA就是典型的周期挪用。当DMA和CPU同时访问总线时,总线仲裁器会让DMA优先,CPU会插入等待周期。你在调试时如果发现某段代码执行时间比预期略长,可能就是因为DMA在偷周期。

3.3 交替访存:理想化但成本高

交替访存方式把内存的存取周期分成两个时间片,一个给CPU用,一个给DMA用。比如存取周期是1微秒,那就分成两个500纳秒,CPU和DMA各用一个。这样双方都不用等,互不干扰。

听起来很美,但实现成本高:需要内存的存取速度足够快,能支持这种分时操作;而且如果某一方没有访存需求,另一个方也不能占用对方的时间片,造成浪费。这种方式在实际中较少使用,考试里出现的频率也低于周期挪用。

3.4 三种方式的对比与选择依据

传送方式CPU影响内存利用率控制复杂度典型场景
停止CPU访存大,完全停止低简单小数据块、低速DMA
周期挪用小,偶尔延迟高中等大多数实际硬件
交替访存无中等复杂高速内存系统

选择哪种方式,核心看两个因素:数据块的实时性要求和CPU的性能损失容忍度。磁盘、网卡这类高速设备通常用周期挪用;一些简单的单片机DMA可能用停止CPU访存;交替访存更多是理论模型。

4. DMA与中断的配合:考试和实战都绕不开的点

4.1 DMA请求与中断请求的本质区别

很多人分不清DMA请求和中断请求,其实两者的触发时机和作用完全不同:

  • DMA请求:在每个数据传送之前触发,DMAC向CPU申请总线使用权。它请求的是“让我用一下总线”,不是“让CPU来处理”。
  • 中断请求:在整个数据块传送完成后触发,DMAC通知CPU“活干完了,你来收尾”。它请求的是CPU的注意力和处理时间。

打个比方:DMA请求像是货车司机每次进仓库前跟门卫打个招呼“我进去拉一趟货”;中断请求像是所有货都拉完了,司机跟老板汇报“任务完成,请验收”。一个是过程性的、频繁的,一个是终结性的、一次性的。

4.2 中断服务程序在DMA流程中的角色

DMA传送完成后,DMAC会发中断请求。CPU响应中断后,进入中断服务程序,主要做几件事:

  1. 检查传送状态:读取DMAC的状态寄存器,确认是正常完成还是出错。
  2. 处理数据:如果传送的是需要CPU进一步处理的数据(比如网络包需要协议栈解析),在这里进行。
  3. 重新初始化DMA:如果是循环传送模式,需要重新设置AR和WC;如果是单次传送,则关闭DMA通道。
  4. 唤醒等待的进程:如果某个进程在等待I/O完成,在这里将其唤醒。

这里有个容易考的点:DMA传送过程中CPU可以响应其他中断吗?答案是可以的。因为DMA传送不占用CPU,CPU只是在每个存取周期被“偷”一下,中断响应和处理照常进行。但要注意,如果DMA正在挪用周期,CPU的中断响应可能会延迟一个存取周期。

4.3 2024年45题的考点还原与解题思路

2024年那道45题,核心考的是DMA传送过程中CPU与DMA对总线的争用关系,以及传送完成后中断的处理时机。题目给了一个具体的传送场景,问在DMA传送期间CPU能否访存、中断何时被响应、传送总时间如何计算。

解题的关键是抓住两点:第一,DMA采用周期挪用方式时,CPU和DMA交替访存,总传送时间等于数据块大小乘以存取周期(假设DMA每次都能及时挪用);第二,中断在最后一个数据传送完成后才触发,中断响应和处理时间要单独计算。

很多同学失分是因为把“DMA请求”和“中断请求”的时序搞混了,以为每个数据传送都会触发中断。记住:DMA请求每个数据一次,中断请求每个数据块一次。

5. 从408到真实硬件:DMA在STM32等平台上的落地

5.1 STM32的DMA控制器架构

STM32的DMA控制器和教材里的DMAC在原理上完全一致,只是实现细节更丰富。以STM32F4为例,它有两个DMA控制器,每个有8个数据流,每个数据流有独立的通道选择。每个数据流内部有:

  • 源地址寄存器和目的地址寄存器(对应教材里的AR和DAR)
  • 数据项数寄存器(对应WC)
  • 控制寄存器:配置传送方向、数据宽度、优先级、循环模式、中断使能等。

配置一个DMA传送的典型流程是:使能DMA时钟、配置数据流参数、设置源和目的地址、设置传送长度、使能数据流。这和教材里“CPU初始化DMAC”的步骤一一对应。

5.2 串口DMA发送的完整配置实例

以STM32的串口DMA发送为例,展示一个可直接参考的配置过程。假设用USART1发送一个缓冲区里的数据:

// 1. 使能时钟 RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN; // 使能DMA2时钟 RCC->APB2ENR |= RCC_APB2ENR_USART1EN; // 使能USART1时钟 // 2. 配置DMA数据流 DMA2_Stream7->CR = 0; // 先关闭数据流 while (DMA2_Stream7->CR & DMA_SxCR_EN); // 等待关闭完成 DMA2_Stream7->PAR = (uint32_t)&USART1->DR; // 外设地址:串口数据寄存器 DMA2_Stream7->M0AR = (uint32_t)tx_buffer; // 内存地址:发送缓冲区 DMA2_Stream7->NDTR = tx_length; // 传送数据项数 DMA2_Stream7->CR = (4 << DMA_SxCR_CHSEL_Pos) // 通道4对应USART1_TX | DMA_SxCR_MINC // 内存地址递增 | DMA_SxCR_DIR_0 // 方向:内存到外设 | DMA_SxCR_TCIE; // 传送完成中断使能 // 3. 使能数据流 DMA2_Stream7->CR |= DMA_SxCR_EN; // 4. 使能串口的DMA发送请求 USART1->CR3 |= USART_CR3_DMAT;

这段代码里,NDTR就是教材里的字计数器,PAR和M0AR对应设备地址和内存地址寄存器。MINC位控制内存地址是否递增——发送缓冲区时通常递增,发送单个寄存器时不需要。

5.3 ADC多通道采集中的DMA应用

ADC多通道采集是DMA的经典应用场景。如果不用DMA,CPU需要在每次ADC转换完成后读取结果,多个通道轮询下来CPU占用率很高。用DMA后,ADC每转换完一个通道,自动触发DMA把结果搬到内存数组里,CPU完全不用管。

配置要点是:ADC设置为扫描模式、连续转换模式,DMA设置为循环模式、外设地址不递增、内存地址递增。这样ADC不断转换,DMA不断搬运,内存里始终保存着最新的各通道采样值。CPU需要数据时直接读数组即可。

实操心得:ADC+DMA配置时最容易踩的坑是DMA的循环模式和ADC的连续模式没配对。如果DMA是单次模式而ADC是连续转换,第一次DMA搬完后就不再搬了,但ADC还在转,数据就丢了。反过来如果DMA是循环模式但ADC只转换一次,DMA会一直搬同一个值。两者必须匹配。

5.4 SPI DMA与串口DMA的差异

SPI用DMA和串口用DMA在原理上一样,但有个细节差异:SPI是全双工,发送和接收同时进行。所以SPI的DMA通常需要配置两个数据流,一个负责发送(内存到SPI数据寄存器),一个负责接收(SPI数据寄存器到内存)。而且SPI的DMA请求是发送和接收分开的,需要分别使能。

另外,SPI的时钟极性和相位配置会影响DMA传送的时序,如果SPI模式配错,DMA搬过来的数据全是乱的。调试时先用轮询方式确认SPI通信正常,再切换到DMA,能省很多排查时间。

6. 常见问题与排查技巧实录

6.1 考试中的高频易错点

易错点错误理解正确理解
DMA传送单位以为是字是数据块
DMA请求频率以为每个数据块一次每个数据一次
中断触发时机以为传送中触发传送完成后触发
周期挪用以为DMAC独占总线只借用单个存取周期
CPU能否访存以为DMA期间CPU完全停止周期挪用方式下CPU可访存
DMA与中断关系以为两者互斥DMA传送完成后用中断通知

6.2 硬件调试中的典型问题

问题一:DMA传送不启动。最常见的原因是时钟没使能,或者数据流在配置前没有正确关闭。STM32的DMA数据流在使能状态下不能修改配置寄存器,必须先清EN位并等待硬件确认关闭。

问题二:传送的数据错位。检查内存地址递增配置是否正确。如果源地址应该递增但没配MINC,每次搬的都是同一个位置的数据。另外检查数据宽度对齐,外设和内存的数据宽度不一致时,DMA的对齐方式会影响结果。

问题三:传送完成中断不触发。确认TCIE位已使能,并且NVIC里对应的中断通道已使能。有些平台还需要清除中断标志位,否则中断会反复触发。

问题四:DMA和CPU同时访问同一块内存导致数据不一致。这在没有缓存一致性机制的单片机上通常不是问题,但在带Cache的处理器上需要特别注意。DMA直接访问内存,不经过Cache,如果CPU的Cache里有旧数据,就会读到错误的值。解决方法是在DMA传送前后进行Cache刷新或无效化操作。

6.3 独家避坑技巧

第一个技巧:先用轮询验证功能,再切DMA。不管是串口、SPI还是ADC,先用最简单的轮询方式确认外设本身工作正常,再配置DMA。这样出问题时能快速定位是外设配置问题还是DMA配置问题。

第二个技巧:DMA传送长度设为实际需要的最小值。有些同学图省事把NDTR设得很大,结果DMA搬了一堆无用数据,还可能越界访问。精确设置传送长度,既安全又高效。

第三个技巧:调试时用DMA传送完成中断翻转一个GPIO。用示波器或逻辑分析仪看这个GPIO的波形,能直观地看到DMA传送的起止时间,对分析时序问题非常有帮助。

第四个技巧:注意DMA的优先级配置。多个DMA数据流同时工作时,优先级决定谁先获得总线。高优先级的数据流如果配置不当,可能饿死低优先级的数据流。一般来说,实时性要求高的(比如ADC采样)设高优先级,大块数据搬运设低优先级。

7. 从教材到考场:唐朔飞与白中英教材的DMA章节怎么读

唐朔飞的《计算机组成原理》在DMA这一节讲得比较细,尤其是三种传送方式的对比和DMA控制器的结构。建议重点看DMA接口与CPU的连接方式、DMA请求与中断请求的区别、以及DMA传送过程的时序图。唐书的课后题里有一道关于DMA传送时间的计算题,非常经典,一定要动手算一遍。

白中英的教材在DMA部分更简洁,但胜在结构清晰。他把DMA控制器分为“选择型”和“多路型”两类,这个分类在考试里偶尔会考到。选择型DMAC一次只能连接一个设备,多路型可以连接多个设备并分时服务。理解这个分类有助于回答“DMA控制器如何管理多个设备”这类问题。

王道考研的辅导书在DMA这一章总结得很好,尤其是“DMA方式与中断方式的区别”那张对比表,几乎每年都会考到类似的点。建议把王道上的相关题目全部做一遍,错题反复看。

提示:408考试里DMA的考查重点集中在三个方面——三种传送方式的区别、DMA与中断的配合、DMA传送时间的计算。把这三点吃透,DMA相关的题目基本不会丢分。

8. 写在最后:DMA思维在系统设计中的延伸

DMA背后的设计思想其实很通用:把机械重复的工作交给专用硬件,让通用处理器专注于它擅长的事情。这个思想在现代计算机系统里随处可见——GPU把图形渲染从CPU手里接过去,网络卸载引擎把协议栈处理从CPU手里接过去,甚至AI加速器把矩阵运算从CPU手里接过去,本质上都是DMA思想的延伸。

我在实际做嵌入式项目时,只要遇到“CPU花大量时间在搬运数据”的情况,第一反应就是看看能不能用DMA。串口收发、ADC采集、SPI通信、内存到内存的拷贝,这些场景用上DMA后,CPU占用率往往能从百分之七八十降到个位数。那种感觉就像从手动挡换到自动挡,一开始可能不习惯,用熟了再也回不去。

如果你正在备考408,DMA这一块建议不要只背概念,找一块STM32开发板实际配一下DMA,看着数据自动从外设搬到内存,你对周期挪用、传送单位、中断配合这些概念的理解会完全不一样。纸上得来终觉浅,这句话在计算机组成原理这门课上尤其成立。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询