ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

DMA方式深度解析:从408考研到STM32实战

DMA方式深度解析:从408考研到STM32实战 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 为什么需要DMACPU不该当搬运工要理解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就设置AR0x2000WC4096假设按字节计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响应中断后进入中断服务程序主要做几件事检查传送状态读取DMAC的状态寄存器确认是正常完成还是出错。处理数据如果传送的是需要CPU进一步处理的数据比如网络包需要协议栈解析在这里进行。重新初始化DMA如果是循环传送模式需要重新设置AR和WC如果是单次传送则关闭DMA通道。唤醒等待的进程如果某个进程在等待I/O完成在这里将其唤醒。这里有个容易考的点DMA传送过程中CPU可以响应其他中断吗答案是可以的。因为DMA传送不占用CPUCPU只是在每个存取周期被“偷”一下中断响应和处理照常进行。但要注意如果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的经典应用场景。如果不用DMACPU需要在每次ADC转换完成后读取结果多个通道轮询下来CPU占用率很高。用DMA后ADC每转换完一个通道自动触发DMA把结果搬到内存数组里CPU完全不用管。配置要点是ADC设置为扫描模式、连续转换模式DMA设置为循环模式、外设地址不递增、内存地址递增。这样ADC不断转换DMA不断搬运内存里始终保存着最新的各通道采样值。CPU需要数据时直接读数组即可。实操心得ADCDMA配置时最容易踩的坑是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占用率往往能从百分之七八十降到个位数。那种感觉就像从手动挡换到自动挡一开始可能不习惯用熟了再也回不去。如果你正在备考408DMA这一块建议不要只背概念找一块STM32开发板实际配一下DMA看着数据自动从外设搬到内存你对周期挪用、传送单位、中断配合这些概念的理解会完全不一样。纸上得来终觉浅这句话在计算机组成原理这门课上尤其成立。
返回列表