1. DMA基础概念:什么是DMA、DMA的工作原理、DMA与CPU的数据搬运对比
各位同学,咱们今天聊聊DMA。说实话,我做了十几年嵌入式开发,DMA这玩意儿几乎天天打交道。很多刚入行的朋友总觉得DMA很神秘,其实说白了,它就是硬件层面的「数据搬运工」。
1.1 什么是DMA
DMA,全称Direct Memory Access,直接存储器访问。我习惯叫它「数据快车道」。
你想想看,没有DMA的时候,CPU得亲自把数据从外设搬到内存,或者从内存搬到外设。这就像一个大老板亲自去搬砖,效率能高吗?DMA就是专门干这个的硬件模块,它不需要CPU插手,自己就能完成数据搬运。
核心要点:DMA是一个独立的硬件控制器,可以在没有CPU参与的情况下,完成外设与内存之间的数据传输。
1.2 DMA的工作原理
DMA的工作流程其实不复杂,我给大家拆解一下:
- 请求阶段:外设(比如UART、SPI、ADC)产生数据,向DMA控制器发送请求信号。
- 仲裁阶段:DMA控制器向CPU请求总线控制权。CPU在总线空闲时让出控制权。
- 传输阶段:DMA接管总线,直接在外设和内存之间搬运数据。
- 结束阶段:传输完成,DMA释放总线,通知CPU「活干完了」。
嗯,这里要注意一个细节:DMA传输期间,CPU其实是被「挂起」的,不能访问总线。但现代处理器有缓存和流水线,影响没那么大。
个人经验:我在做某款工业相机项目时,用DMA搬运图像数据,CPU占用率从85%直接降到12%。那感觉,就像给系统装了个涡轮增压。
1.3 DMA与CPU的数据搬运对比
咱们直接上对比表,一目了然:
| 对比项 | CPU搬运 | DMA搬运 |
|---|---|---|
| 控制方式 | 软件指令控制 | 硬件自动控制 |
| 速度 | 受限于指令执行周期 | 接近总线极限速度 |
| CPU占用 | 100%占用,无法做其他事 | 几乎零占用 |
| 适用场景 | 小数据量、非实时 | 大数据量、实时性要求高 |
| 灵活性 | 高,可随时修改逻辑 | 低,需预先配置 |
| 功耗 | 较高(CPU持续运行) | 较低(专用硬件完成) |
说白了,CPU搬运就像你亲自去快递站取件,DMA搬运就像让快递小哥直接送到家门口。一个费时费力,一个省心省力。
避坑指南:我曾经在一个项目中,用CPU轮询方式读取ADC数据,结果CPU忙得连系统心跳都跑不准了。后来换成DMA + 中断方式,问题迎刃而解。记住:能用DMA的地方,别让CPU干苦力活。
1.4 实际代码示例
咱们看一个简单的DMA配置代码,以STM32为例:
// DMA传输配置示例
void DMA_Config(void)
{
// 1. 使能DMA时钟
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
// 2. 配置DMA通道
DMA1_Channel6->CPAR = (uint32_t)&USART1->DR; // 外设地址
DMA1_Channel6->CMAR = (uint32_t)rx_buffer; // 内存地址
DMA1_Channel6->CNDTR = BUFFER_SIZE; // 传输数据量
// 3. 配置传输方向:外设到内存
DMA1_Channel6->CCR |= DMA_CCR_DIR;
// 4. 使能DMA通道
DMA1_Channel6->CCR |= DMA_CCR_EN;
}
这段代码看着简单,但背后涉及的东西不少。外设地址、内存地址、传输方向、数据宽度...每一个参数都直接影响系统稳定性。
1.5 什么时候该用DMA?
我给大家总结几个典型场景:
- 大数据量传输:比如音频播放、视频采集、文件读写
- 周期性数据搬运:比如ADC连续采样、定时器触发传输
- 实时性要求高:比如电机控制、传感器数据采集
- 低功耗场景:CPU可以进入休眠,DMA默默干活
反过来,如果只是传几个字节的数据,或者数据量很小,用DMA反而得不偿失。为什么?因为DMA的配置开销可能比直接CPU搬运还大。这个道理,就像你叫个外卖只买一瓶水,配送费比水还贵。
我的建议:刚开始接触DMA时,先从简单的UART接收开始练手。配置简单,效果明显,出了问题也好排查。等熟悉了再挑战复杂场景。
好了,这一章的内容就到这里。DMA的概念其实不复杂,关键是要理解它「解放CPU」的核心思想。下一章咱们聊聊DMA在设备树中的描述方式,那才是真正实战的开始。