
本文概述
DMA(直接存储器访问)是STM32中提高数据传输效率的核心外设。面试中需要讲清DMA的基本结构(通道/请求映射、仲裁优先级)、传输模式(正常/循环/内存到内存)、数据宽度对齐、FIFO模式、中断与半传输中断,以及Cache一致性问题(D-Cache使能时DMA缓冲区必须用MPU配置为非缓存或手动清理/失效缓存)。
核心要点
STM32 DMA分DMA1和DMA2,每个有多个通道(Stream),每个通道支持特定的外设请求
传输模式:正常模式(传输完成后停止)、循环模式(自动重装,适合连续数据采集)、内存到内存模式(无需外设触发)
数据宽度:源和目标数据宽度可以不同(8/16/32位),DMA会自动打包/解包,但要注意地址对齐
FIFO模式:DMA有FIFO缓冲区(通常4个字),可以减少总线访问次数,支持突发传输和阈值配置
Cache一致性:使能D-Cache后,DMA写内存前要Clean Cache(CPU写→DMA读),DMA写完后要Invalidate Cache(DMA写→CPU读),或用MPU把DMA缓冲区设为非缓存区
面试官考察点
面试官考察的是DMA的深层理解和工程调试经验。
配置能力:能否说出DMA配置的完整步骤(时钟、通道、方向、数据宽度、模式、优先级、中断)
模式理解:循环模式和正常模式的区别和适用场景,半传输中断的作用
Cache问题:是否知道D-Cache对DMA的影响,怎么解决——这是区分初级和中级的关键
调试经验:DMA传输异常时怎么排查(配置错误、地址对齐、总线冲突、中断优先级)
回答思路
按"结构→配置→模式→优化→调试"五层回答:
结构:DMA1/DMA2、通道/请求映射、仲裁优先级
配置步骤:时钟→通道选择→方向→数据宽度→模式→优先级→缓冲区地址→中断→使能
模式:正常/循环/内存到内存,半传输中断的应用(双缓冲)
优化:FIFO模式、突发传输、Cache一致性处理
调试:常见问题和排查方法
参考回答
STM32 DMA配置和优化我一般从五个层面处理。
第一,DMA结构和通道映射。STM32F4/F7/H7系列有DMA1和DMA2两个控制器,每个有8个Stream(F4)或更多(H7有BDMA和DMA1/DMA2)。每个Stream可以映射到不同的外设请求(比如USART1_RX、SPI1_RX、ADC1等),通过DMA_SxCR寄存器的CHSEL位选择。仲裁优先级分四个等级:低、中、高、极高,同优先级时按Stream编号(0最高)。需要注意DMA1和DMA2的请求映射不同,比如ADC只能用DMA2,USART2可以用DMA1。设计时要查参考手册的DMA请求映射表,不能随便选通道。
第二,配置步骤。完整的配置流程是:1) 使能DMA时钟(RCC_AHB1ENR);2) 配置DMA_SxCR:通道选择、数据传输方向(外设到内存、内存到外设、内存到内存)、数据宽度(8/16/32位,源和目标可以不同)、循环模式使能、优先级、内存/外设地址增量模式;3) 配置DMA_SxNDTR:传输数据量;4) 配置DMA_SxPAR:外设地址;5) 配置DMA_SxM0AR:内存地址(双缓冲时还有M1AR);6) 配置FIFO(DMA_SxFCR):FIFO使能、阈值、突发配置;7) 配置中断(DMA_SxCR的TEIE/HTIE/TCIE),并在NVIC中使能中断;8) 使能DMA Stream(DMA_SxCR的EN位)。HAL库的话用HAL_DMA_Init()和HAL_DMA_Start()或HAL_UART_Transmit_DMA()等封装函数。
第三,传输模式。正常模式(Normal):传输完成后DMA停止,需要重新配置NDTR和使能才能再次传输,适合单次数据传输。循环模式(Circular):传输完成后自动重装NDTR,连续传输,适合ADC连续采样、UART连续接收等场景。内存到内存模式(M2M):不需要外设触发,DMA自动从源地址读数据写到目标地址,适合内存拷贝(比如从Flash拷贝到RAM),但M2M模式不能用循环模式。半传输中断(HTI):传输到一半时触发中断,配合循环模式可以实现双缓冲——前半区CPU处理时DMA写后半区,后半区CPU处理时DMA写前半区,避免数据覆盖。这在音频处理、高速数据采集中很常用。
第四,FIFO和优化。DMA有FIFO缓冲区(F4系列每个Stream 4个字=16字节),使能FIFO后可以:1) 减少DMA访问总线的次数(攒够一批再传输),降低总线占用;2) 支持突发传输(INCR4/INCR8/INCR16),提高效率;3) 支持源和目标数据宽度不同时的打包/解包。FIFO阈值可以设为1/4、1/2、3/4或满,阈值越小延迟越低但总线访问越频繁。另外,DMA和CPU同时访问内存时会发生总线冲突,DMA优先级高时会占用总线,导致CPU等待。优化方法:1) 把DMA缓冲区放在不同的内存区域(比如CPU用CCM,DMA用SRAM1),避免总线冲突;2) 用FIFO和突发传输减少DMA总线访问次数;3) 合理设置DMA优先级,不要所有DMA都设为极高。
第五,常见问题调试。DMA不传输:检查时钟是否使能、通道/请求映射是否正确、NDTR是否为0、外设是否发出DMA请求(比如USART的DMAT位是否使能)。传输数据错误:检查地址对齐(32位传输要求4字节对齐)、数据宽度配置、内存/外设地址增量模式。传输偶尔丢失:检查中断优先级(DMA中断被更高优先级中断阻塞)、总线冲突、FIFO溢出。HardFault:检查缓冲区地址是否有效、是否越界、栈是否溢出。

扫码关注



























