
DMA这三个字母但凡翻过几页计算机组成原理的人都不陌生。但我在带考研学生和做嵌入式开发的两拨人之间来回切换时发现一个很有意思的现象考研的同学能把DMA的定义背得滚瓜烂熟什么直接存储器存取不需要CPU干预在主存和外设之间开辟直接数据通路但一问到为什么DMA能绕过CPU周期挪用到底挪的是哪个周期DMA和中断到底怎么配合就开始支支吾吾而做嵌入式的工程师天天配DMA通道却未必说得清楚408考纲里DMA控制器的内部结构和工作阶段划分。这篇东西就是想把这两条线打通——既把408考试里DMA的考点逻辑讲透也把实际配置DMA时那些文档里不会写的坑说清楚。不管你是正在啃唐朔飞还是王道还是在用STM32、GD32、AT32这些片子做串口DMA收发下面这些内容应该都能对上你的需求。1. 为什么DMA不是更快的程序查询而是I/O控制方式的一次范式转换1.1 从程序查询到中断再到DMACPU被绑住的程度在变要理解DMA得先把前面两种方式的问题说清楚。程序查询方式下CPU发出I/O指令后就不停地读设备状态寄存器设备没准备好就继续读准备好了就传一个数据然后接着读下一个。这种方式的问题不是慢这么简单而是CPU在等待期间完全被绑死什么也干不了。你可以想象成你去银行办业务柜台说系统在加载你站这儿等着你就只能站着不能去填别的表。中断方式改善了一点CPU发出I/O指令后可以去执行别的程序设备准备好数据后通过中断线通知CPUCPU暂停当前程序转去执行中断服务程序完成一次数据传送然后返回。但注意每次传送一个数据或者一小批数据都要经历一次完整的中断响应过程——保存断点、关中断、取中断向量、执行服务程序、恢复现场、开中断。对于高速设备比如磁盘、网卡来说数据像流水一样来如果每个字节或每个字都中断一次CPU光处理中断上下文就忙不过来了。DMA的思路完全不同它不是在CPU怎么参与传送上做优化而是直接引入一个专门的硬件控制器DMA控制器DMAC让这个控制器来接管数据传送这件事。CPU只需要在传送开始前告诉DMAC从哪传到哪、传多少、传完了告诉我然后就可以去干别的事了。整个数据传送过程由DMAC硬件自主完成CPU完全不介入。这里有一个关键认知DMA不是更快的程序查询也不是更高效的中断它是I/O控制方式的一次范式转换——从CPU主导数据传送变成专用硬件主导数据传送。这个转换的意义在于CPU终于从数据搬运工的角色中解放出来可以专注于计算和控制。1.2 DMA方式的核心特征三条总线权的转移DMA之所以能绕过CPU本质上是它拿到了总线控制权。在正常的冯诺依曼结构中CPU是总线的主控者所有对主存的访问都要经过CPU或者至少由CPU发起。但DMA方式下DMAC可以向CPU发出总线请求HOLDCPU在当前总线周期结束后响应发出总线允许HLDA把总线控制权交给DMAC。DMAC拿到总线权后就可以像CPU一样直接对主存进行读写操作。这个过程涉及三条总线权的转移地址总线、数据总线、控制总线。DMAC需要自己产生地址信号告诉主存读写哪个单元、自己产生读写控制信号告诉主存是读还是写、自己处理数据传送。这就是为什么DMAC内部必须有地址寄存器、字计数器、状态寄存器等部件。考试里经常考的一个点是DMA传送过程中CPU是否完全停止工作答案是CPU暂时放弃总线控制权但CPU内部的操作比如指令译码、算术运算可能还在继续只是无法访问主存。如果CPU当前执行的指令不需要访问主存比如寄存器间的运算那它甚至可以继续执行。但一旦需要访存就必须等待DMA释放总线。1.3 DMA与中断的本质区别谁在搬数据很多人把DMA和中断混在一起理解觉得DMA就是中断的升级版。这个理解是错的。中断方式下数据传送是由CPU执行中断服务程序完成的——CPU亲自把数据从I/O接口读到寄存器再写到主存。DMA方式下数据传送是由DMAC硬件完成的——CPU根本不碰数据数据直接在DMAC的控制下从I/O设备流向主存或反向。打个比方中断方式像是你请了一个助理但每次有快递来助理都要跑过来问你这个放哪你告诉他之后他再放。DMA方式像是你给助理一把仓库钥匙和一张清单告诉他按清单上的地址放放完了跟我说一声然后你就可以去开会了。这个区别决定了DMA的适用场景高速、大批量的数据传送。比如磁盘读写、网络数据包收发、图像采集等。对于低速设备比如键盘用DMA反而浪费——因为DMAC的初始化和总线权切换也是有开销的。2. DMA控制器的内部结构考试画图题和实际芯片的对应关系2.1 408考纲要求的DMAC组成部件唐朔飞教材里给出的DMAC结构图是考试的重点。一个典型的DMAC包含以下部件主存地址寄存器AR存放要访问的主存地址每传送一个数据后自动加1或减1。字计数器WC存放剩余要传送的字数每传送一个数据后自动减1减到0时发出结束信号。数据缓冲寄存器DR暂存传送中的数据。DMA请求触发器接收I/O设备的DMA请求信号。控制/状态逻辑产生DMA请求信号向CPU、接收DMA响应信号、控制传送过程。中断机构当字计数器减到0时向CPU发出中断请求通知传送完成。这些部件在考试里经常以框图形式出现要求你标注各部件名称并说明其作用。我建议的记忆方式是地址、计数、缓冲、请求、控制、中断——六个关键词对应六个部件。2.2 实际芯片里的DMA控制器以STM32为例如果你用过STM32的DMA你会发现实际芯片里的DMA控制器比教材里的框图复杂得多但核心逻辑是一致的。STM32的DMA控制器有多个通道比如STM32F103有7个通道每个通道有外设地址寄存器CPAR对应教材里的I/O设备地址。存储器地址寄存器CMAR对应教材里的主存地址寄存器。数据数量寄存器CNDTR对应教材里的字计数器。控制寄存器CCR配置传送方向、数据宽度、循环模式、优先级等。你看教材里的AR和WC在实际芯片里就是CMAR和CNDTR只是名字不同。教材里的数据缓冲寄存器在实际芯片里可能不是一个独立的寄存器而是集成在数据通路里。教材里的中断机构在实际芯片里对应的是DMA传输完成中断、半传输中断、传输错误中断等。我在带学生做STM32串口DMA实验时经常让他们先把教材里的DMAC框图画一遍然后在STM32参考手册里找到对应的寄存器一一对应。这样做的好处是考试的时候看到框图题不会慌做实验的时候也知道每个寄存器在干什么。2.3 地址寄存器和字计数器的自动修改逻辑考试里经常考的一个细节是DMA传送过程中主存地址寄存器和字计数器是如何变化的答案是每传送一个数据地址寄存器加1或减1取决于传送方向字计数器减1。当字计数器减到0时传送结束DMAC向CPU发出中断请求。这个自动加1/减1是硬件实现的不需要CPU干预。在实际芯片里这个功能由DMA通道的硬件逻辑自动完成。你在配置STM32的DMA时只需要设置起始地址和传送数量剩下的地址递增和计数递减都是硬件自动做的。但这里有一个坑不是所有DMA通道都支持地址递增。比如STM32的DMA在外设端通常不支持地址递增因为外设寄存器地址固定但在存储器端支持递增。如果你配置错了数据就会全部传到同一个地址覆盖掉之前的数据。这个坑我在实际项目中踩过——当时用DMA采集ADC多通道数据忘了配置存储器地址递增结果所有通道的数据都堆在同一个数组元素里查了半天才发现是DMA配置的问题。3. DMA传送的三种方式停止CPU访存、周期挪用、交替访存3.1 停止CPU访存方式简单但浪费这种方式下DMAC向CPU发出总线请求后CPU放弃总线控制权直到DMA传送全部完成才恢复。也就是说在整个DMA传送期间CPU完全不能访存。这种方式的优点是控制简单DMAC不需要复杂的时序逻辑。缺点是CPU在DMA传送期间无法访存如果DMA传送时间很长比如传送一个大文件CPU的效率会大幅下降。考试里经常问这种方式适合什么场景答案是适合DMA传送时间短、CPU在此期间不需要访存的场景。比如传送一个数据块传送时间很短CPU等一下也无所谓。3.2 周期挪用方式DMA和CPU交替使用总线这种方式下DMAC不是一直占用总线而是在需要传送数据时才向CPU发出总线请求挪用一两个总线周期来传送数据传送完成后立即释放总线。CPU在DMAC不占用总线的周期里可以正常访存。这种方式的关键是周期挪用——DMAC挪用的是CPU的总线周期。具体来说当I/O设备准备好一个数据后DMAC向CPU发出总线请求CPU在当前总线周期结束后响应DMAC占用一个总线周期完成数据传送然后释放总线。下一个数据准备好后再重复这个过程。这种方式的优点是CPU和DMA可以交替使用总线CPU的效率比停止CPU访存方式高。缺点是DMAC需要更复杂的时序控制逻辑而且每次传送都要请求总线有一定的开销。考试里经常考的一个计算题是假设CPU的工作周期为TDMA传送一个数据需要占用一个总线周期I/O设备准备好一个数据的时间为t问DMA传送对CPU效率的影响。这类题目的关键是搞清楚DMA占用总线的频率和每次占用的时间。3.3 交替访存方式把总线周期分给CPU和DMA这种方式下总线周期被分成两个时间片一个给CPU一个给DMA。CPU和DMA交替使用总线不需要总线请求和响应过程。这种方式的优点是效率高因为不需要总线权的切换开销。缺点是需要更复杂的时序控制而且对CPU和DMA的时序配合要求很高。这种方式在实际芯片里不太常见但在考试里是一个重要的知识点。3.4 三种方式的对比与选择方式总线权切换CPU效率控制复杂度适用场景停止CPU访存有低简单DMA传送时间短周期挪用有中中等高速设备、大批量传送交替访存无高复杂对效率要求极高的场景在实际芯片里STM32的DMA采用的是周期挪用方式——DMA在需要传送数据时占用总线传送完成后释放。你在配置STM32的DMA时可以设置通道优先级高优先级的通道可以优先占用总线。这个优先级机制在多个DMA通道同时工作时非常重要。4. DMA传送的完整过程从请求到中断的五个阶段4.1 第一阶段CPU初始化DMACDMA传送开始前CPU需要做以下初始化工作设置主存地址寄存器AR的初值——告诉DMAC数据要传到主存的哪个位置。设置字计数器WC的初值——告诉DMAC要传送多少个数据。设置传送方向——是读从主存到I/O设备还是写从I/O设备到主存。启动I/O设备——让设备开始准备数据。如果DMAC有多个通道还需要设置通道优先级。这些初始化工作是通过CPU执行I/O指令完成的。在实际芯片里就是配置DMA的各个寄存器。比如在STM32里你需要配置CPAR、CMAR、CNDTR、CCR等寄存器。这里有一个考试常考的细节DMA传送前CPU需要执行I/O指令来初始化DMAC但DMA传送过程中CPU不再执行I/O指令。这个区别是DMA和程序查询、中断方式的重要区别。4.2 第二阶段I/O设备发出DMA请求I/O设备准备好一个数据后向DMAC发出DMA请求信号。这个信号告诉DMAC我有一个数据要传送了。在实际芯片里这个请求信号可能是外设的DMA请求线比如STM32的ADC、USART、SPI等外设都有DMA请求线。当外设的数据寄存器准备好后硬件自动拉高DMA请求线通知DMAC。4.3 第三阶段DMAC向CPU发出总线请求DMAC收到I/O设备的DMA请求后向CPU发出总线请求信号HOLD。这个信号告诉CPU我要用总线了请你让一下。CPU收到总线请求后会在当前总线周期结束后响应发出总线允许信号HLDA把总线控制权交给DMAC。注意CPU不是立即响应而是等当前总线周期结束后才响应。这个当前总线周期结束是一个关键的时间点——如果CPU正在执行一条需要多个总线周期的指令DMAC需要等到这条指令的所有总线周期都结束后才能拿到总线权。4.4 第四阶段DMAC控制数据传送DMAC拿到总线权后开始控制数据传送。具体过程是DMAC把主存地址寄存器AR的内容送到地址总线上。DMAC向主存和I/O设备发出读写控制信号。数据通过数据总线在主存和I/O设备之间传送。每传送一个数据AR加1或减1WC减1。如果WC不为0继续传送下一个数据如果WC为0传送结束。这个过程中DMAC需要自己产生地址信号和读写控制信号所以DMAC必须有时序控制逻辑。在实际芯片里这个逻辑由DMA通道的硬件自动完成你只需要配置好寄存器就行。4.5 第五阶段传送结束DMAC发出中断请求当字计数器WC减到0时DMAC知道所有数据都传送完了。它会释放总线控制权撤销HOLD信号然后向CPU发出中断请求通知CPUDMA传送完成了。CPU收到中断请求后执行中断服务程序做后续处理比如处理数据、启动下一次传送等。这个中断是DMA传送的收尾——虽然DMA传送过程中CPU不参与但传送完成后CPU需要知道传送结果。考试里经常考的一个问题是DMA传送结束后CPU是如何知道的答案是通过中断。DMAC在传送结束后向CPU发出中断请求CPU执行中断服务程序来处理后续工作。这个中断和普通的中断没有本质区别只是触发源是DMAC而不是I/O设备。5. DMA与中断的配合为什么DMA传送完成后还需要中断5.1 DMA不处理异常中断负责善后DMA传送过程中DMAC只负责搬数据不负责判断数据是否正确、是否需要重传、是否需要通知上层应用。这些善后工作是由CPU通过中断服务程序完成的。比如在网络数据包接收中DMA把数据包从网卡搬到主存后发出中断通知CPU。CPU在中断服务程序里检查数据包的校验和、解析协议头、通知上层应用。如果没有中断CPU就不知道数据包已经接收完了。5.2 中断服务程序里通常做什么在DMA传送完成的中断服务程序里CPU通常做以下工作检查DMA传送是否成功有没有错误标志。处理接收到的数据比如解析、校验、转发。准备下一次DMA传送重新设置AR和WC。唤醒等待数据的进程或线程。在实际的嵌入式开发中DMA传输完成中断的服务程序通常很短——只做标志位的设置和数据的初步处理复杂的处理放在主循环里做。这是因为中断服务程序应该尽量短避免影响其他中断的响应。5.3 半传输中断和循环模式实际开发中的常用技巧在实际芯片里DMA通常还支持半传输中断和循环模式。半传输中断是指当传送了一半数据时触发中断这样CPU可以在DMA还在传送后半部分数据时就开始处理前半部分数据实现乒乓缓冲。循环模式是指DMA传送完成后自动重新开始不需要CPU重新配置。这在连续数据采集比如ADC连续采样、串口连续接收中非常有用。我在做串口DMA接收时通常会用循环模式加半传输中断和传输完成中断。这样串口数据可以连续接收CPU在半传输中断里处理前半缓冲区的数据在传输完成中断里处理后半缓冲区的数据。这种方式可以避免数据丢失而且CPU的负担很小。6. 从408考题到实际配置DMA知识点在考试和开发中的不同侧重6.1 408考试里DMA的常见考法408考试里DMA的考点主要集中在以下几个方面DMA的基本概念和特点选择题。DMAC的组成部件和作用简答题或框图题。DMA传送的三种方式及其区别选择题或简答题。DMA传送的过程简答题。DMA与中断的区别和配合综合题。计算题DMA传送对CPU效率的影响。其中计算题是很多人的难点。比如假设CPU的工作周期为100nsDMA传送一个数据需要占用一个总线周期100nsI/O设备准备好一个数据的时间为1μs问DMA传送对CPU效率的影响。这类题目的关键是算出DMA占用总线的频率和每次占用的时间然后算出CPU可用时间的比例。6.2 实际开发中DMA配置的关键参数在实际开发中配置DMA时需要注意以下参数传送方向外设到存储器、存储器到外设、存储器到存储器。数据宽度字节、半字、字。外设和存储器的数据宽度要匹配否则会出现数据错位。地址递增外设端通常不递增存储器端通常递增。循环模式连续传送时使用。优先级多个通道同时工作时的仲裁。中断使能传输完成、半传输、传输错误。这些参数在STM32的DMA配置里都有对应的寄存器位。配置错了DMA要么不工作要么工作不正常。6.3 一个真实的踩坑案例串口DMA接收数据错位我曾经在一个项目里用STM32的串口DMA接收数据配置的是字节宽度、存储器地址递增、循环模式。但接收到的数据总是错位——第一个字节跑到第二个位置第二个字节跑到第三个位置。查了半天发现是串口的数据寄存器配置成了半字宽度而DMA配置的是字节宽度。串口每次发送一个半字两个字节但DMA只搬一个字节导致数据错位。这个坑的教训是DMA的数据宽度必须和外设的数据宽度匹配。串口的数据寄存器是8位的DMA就应该配置成字节宽度如果串口配置成了9位数据带校验位DMA可能需要配置成半字宽度。这个细节在参考手册里不会特别强调但实际开发中很容易踩坑。7. DMA传送效率的量化分析考试计算题和实际性能评估7.1 考试里的DMA效率计算考试里经常考的一类题目是假设CPU的工作周期为TDMA传送一个数据需要占用一个总线周期I/O设备准备好一个数据的时间为t求DMA传送对CPU效率的影响。这类题目的解题思路是算出DMA传送一个数据的频率每t时间传送一个数据。算出DMA每次占用总线的时间一个总线周期T。算出DMA占用总线的比例T/t。CPU可用时间的比例1 - T/t。比如T100nst1μs则DMA占用总线的比例为100ns/1μs10%CPU可用时间的比例为90%。如果考虑DMA传送的总数据量还需要算出总传送时间和CPU可用时间。比如传送1000个数据总传送时间为1000×1μs1msDMA占用总线的时间为1000×100ns100μsCPU可用时间为900μs。7.2 实际开发中的DMA性能评估在实际开发中评估DMA性能时需要考虑以下因素总线带宽DMA传送占用总线带宽如果总线带宽不足DMA传送会变慢。总线仲裁开销每次DMA请求和响应都有开销如果传送的数据量很小开销占比会很高。CPU访存冲突DMA传送时CPU如果也需要访存会产生冲突降低CPU效率。外设速度DMA传送速度受外设速度限制如果外设速度很慢DMA的效率优势不明显。在实际项目中我通常会用示波器或者逻辑分析仪测量DMA传送的实际时间然后和理论计算值对比。如果实际时间远大于理论值说明有额外的开销比如总线仲裁、中断处理等。7.3 DMA测速软件和实际测试方法热词里提到了dma测速软件这在实际开发中确实是一个需求。测试DMA性能的方法通常有GPIO翻转法在DMA传送开始和结束时翻转GPIO用示波器测量时间。定时器计数法用定时器记录DMA传送的周期数算出传送时间。内存对比法DMA传送完成后对比源数据和目标数据确认传送正确性。吞吐量测试连续传送大量数据测量单位时间内的传送量。在STM32上我通常用定时器来测量DMA传送时间。具体做法是在DMA传送开始前启动定时器在DMA传输完成中断里停止定时器读取定时器的计数值算出传送时间。这种方法精度高而且不需要额外的硬件。8. 不同芯片平台的DMA实现差异STM32、GD32、AT32的对比8.1 STM32的DMA架构STM32的DMA控制器通常有多个通道比如STM32F103有7个通道STM32F4有16个流每个通道可以独立配置。STM32的DMA支持外设到存储器、存储器到外设、存储器到存储器三种传送方向支持字节、半字、字三种数据宽度支持循环模式和普通模式。STM32的DMA请求映射是固定的——每个通道对应特定的外设请求。比如STM32F103的DMA1通道4对应USART1_TX通道5对应USART1_RX。你在配置DMA时需要查参考手册的DMA请求映射表确认哪个通道对应哪个外设。8.2 GD32的DMA架构GD32的DMA架构和STM32非常相似很多寄存器都是兼容的。但GD32的DMA在某些细节上有差异比如中断标志位的清除方式、通道优先级的仲裁方式等。如果你从STM32迁移到GD32大部分DMA代码可以直接用但需要注意这些细节差异。8.3 AT32的DMA架构AT32的DMA架构也和STM32相似但在DMA请求映射上有所不同。AT32的DMA通道可以灵活映射到不同的外设不像STM32那样固定。这个灵活性在某些应用场景下很有用但也增加了配置的复杂度。我在实际项目中用过STM32、GD32和AT32的DMA感受是STM32的DMA配置最成熟文档最全GD32的DMA和STM32最接近迁移成本最低AT32的DMA最灵活但需要仔细阅读参考手册。不管用哪个平台核心概念都是一样的——地址、计数、方向、宽度、模式、优先级。8.4 跨平台DMA配置的通用思路不管你用哪个平台的DMA配置的思路都是一样的确定传送方向外设到存储器、存储器到外设、存储器到存储器。确定数据宽度字节、半字、字。配置源地址和目标地址。配置传送数量。配置地址递增模式。配置循环模式或普通模式。配置优先级。使能中断如果需要。使能DMA通道。这个思路在STM32、GD32、AT32上都适用只是寄存器的名字和位定义不同。9. DMA在实际项目中的典型应用场景9.1 串口DMA收发最常用的场景串口DMA收发是DMA最常用的场景之一。用DMA接收串口数据时CPU不需要每个字节都中断一次而是等一整批数据接收完成后才中断一次。这大大降低了CPU的负担特别是在高波特率下。配置串口DMA接收的步骤是配置串口的波特率、数据位、停止位、校验位。配置DMA通道源地址为串口数据寄存器目标地址为接收缓冲区数据宽度为字节地址递增存储器端循环模式。使能串口的DMA接收请求。使能DMA通道。在DMA传输完成中断里处理数据。这里有一个坑串口DMA接收时如果数据量不确定比如接收不定长数据需要用空闲中断来判断一帧数据是否接收完成。STM32的串口有空闲中断IDLE当串口总线空闲时触发中断可以在中断里计算接收到的数据长度。9.2 ADC多通道采集DMA提高采样效率ADC多通道采集时用DMA可以把转换结果自动搬到内存数组里不需要CPU每次转换完成后都去读ADC数据寄存器。配置ADC的DMA时需要设置ADC为扫描模式、连续转换模式DMA为循环模式存储器地址递增。这个场景我在实际项目中用过很多次。比如用STM32的ADC采集8个通道的模拟量配置DMA循环模式ADC连续转换DMA自动把8个通道的数据搬到数组里。CPU只需要定期读取数组就行完全不需要干预ADC的转换过程。9.3 SPI DMA传输高速数据交换SPI的速率通常比串口高很多用DMA传输可以充分发挥SPI的速率优势。配置SPI DMA时需要注意SPI的数据宽度8位或16位和DMA的数据宽度匹配。9.4 存储器到存储器DMA数据搬运存储器到存储器的DMA传送在数据搬运场景中很有用。比如把一块数据从Flash搬到RAM或者把一块数据从RAM的一个区域搬到另一个区域。这种传送不需要外设参与DMAC直接控制主存的读写。需要注意的是不是所有DMA控制器都支持存储器到存储器传送。STM32的DMA1不支持存储器到存储器DMA2支持。在配置前需要确认芯片的DMA是否支持这个功能。10. 复习DMA知识点的几个实用建议10.1 用数据流向图串联所有知识点DMA的知识点比较散——有DMAC的结构、有传送方式、有传送过程、有和中断的配合。我建议用一张数据流向图把这些知识点串起来从I/O设备发出DMA请求到DMAC向CPU请求总线到DMAC控制数据传送到传送完成后发出中断。这张图可以把大部分知识点都涵盖进去。10.2 把教材框图和实际芯片寄存器对应起来如果你既考研又做嵌入式最好的复习方式是把教材里的DMAC框图和实际芯片的DMA寄存器对应起来。教材里的AR对应CMARWC对应CNDTRDR对应数据通路中断机构对应DMA中断。这样既加深了对教材的理解又提高了实际开发能力。10.3 计算题要多练搞清楚每个时间参数的含义DMA的计算题不难但容易搞混时间参数。关键是要搞清楚CPU的工作周期、总线周期、DMA传送一个数据的时间、I/O设备准备好一个数据的时间这几个参数之间的关系。多练几道题把每个参数的含义搞清楚考试时就不会慌。10.4 实际配置DMA时先画时序图在实际配置DMA时我建议先画一张时序图——标出DMA请求、总线请求、总线响应、数据传送、中断请求的时间关系。这张图可以帮助你理解DMA的工作过程也可以帮助你在调试时定位问题。比如如果DMA不工作你可以检查是DMA请求没发出还是总线请求没响应还是数据传送出错。10.5 注意DMA和Cache的一致性问题在高性能处理器比如ARM Cortex-A系列中DMA和Cache的一致性是一个重要问题。DMA直接访问主存不经过Cache如果Cache里有对应的数据就会出现数据不一致。解决方法是使用一致性内存或者手动刷新Cache。这个问题在408考试里不考但在实际开发中很重要。我在实际项目中遇到过这个问题用DMA接收网卡数据后CPU读到的还是Cache里的旧数据。后来在DMA传送前刷新了Cache问题就解决了。这个坑在嵌入式Linux开发中很常见做裸机开发时如果用了Cache也需要注意。10.6 多通道DMA的优先级仲裁当多个DMA通道同时请求时DMAC需要仲裁哪个通道先传送。STM32的DMA优先级分为四级最高、高、中、低。如果两个通道的优先级相同则通道号小的优先。在实际项目中高速外设比如SPI、ADC应该配置高优先级低速外设比如串口可以配置低优先级。这个优先级仲裁机制在考试里不考但在实际开发中很重要。如果优先级配置不当高速外设的数据可能会丢失。10.7 DMA传输错误的中断处理DMA传输过程中可能会出现错误比如总线错误、地址错误等。STM32的DMA有传输错误中断可以在中断里处理错误。在实际项目中我通常会在DMA传输错误中断里记录错误标志然后重新初始化DMA通道。这个错误处理机制在考试里不考但在实际开发中是必须的。10.8 从408考题看DMA的考试重点最后说一下408考题里DMA的考试重点。根据我对历年真题的分析DMA的考点主要集中在DMA的基本概念选择题1-2分。DMAC的组成简答题2-3分。DMA传送方式选择题或简答题2-3分。DMA传送过程简答题3-4分。DMA与中断的区别综合题3-4分。其中DMA传送过程和DMA与中断的区别是高频考点几乎每年都考。计算题出现的频率较低但一旦出现就是大题。我在复习DMA时会把教材里的DMA章节反复看三遍第一遍理解概念第二遍记忆细节第三遍做课后题。唐朔飞的课后题里有很多DMA的题目做完之后对知识点的理解会深很多。10.9 用实际项目经验反哺考试理解如果你既做嵌入式开发又考研你会发现实际项目经验对考试理解有很大帮助。比如你实际配置过STM32的DMA再来看教材里的DMAC框图就会觉得非常直观——AR就是CMARWC就是CNDTR中断机构就是DMA中断。这种理论联系实际的学习方式比死记硬背效率高得多。10.10 注意DMA在不同教材里的表述差异不同教材对DMA的表述可能有差异。比如唐朔飞教材里把DMA传送方式分为三种停止CPU访存、周期挪用、交替访存。而有些教材可能分为两种或四种。考试时以目标院校的指定教材为准。如果你不确定用哪本教材可以查目标院校的考试大纲。我在带学生复习时会让他们先确认目标院校的指定教材然后按照教材的表述来复习。不同教材的表述差异不大但细节上可能有出入考试时以指定教材为准最稳妥。