DMA传输类型:四种搬运模式详解
大家好,我是你们的芯片架构设计讲师。今天我们来聊聊DMA的四种基本传输类型。说实话,这四种模式是DMA引擎的核心,搞懂了它们,你基本就掌握了DMA设计的半壁江山。
我在做第一个DMA控制器项目时,就因为这四种模式的理解不够透彻,导致后面调试花了两周时间。嗯,咱们今天一次性把它们讲清楚。
1. 内存到内存(M2M)
这是最基础的模式,说白了就是数据从一个内存地址搬到另一个内存地址。CPU只需要告诉DMA:「源地址在这,目标地址在那,搬多少数据」,然后就可以去干别的事了。
核心特点:
- 源和目标都在系统内存中
- 不需要外设参与
- 常用于数据拷贝、缓冲区刷新
我个人习惯把M2M叫做「内存搬运工」。你想想看,如果没有DMA,CPU得一条条指令去读内存、写内存,效率极低。我曾在项目中用M2M模式做图像帧的拷贝,原来CPU占用率高达80%,换成DMA后直接降到5%。
// M2M传输配置示例(伪代码)
dma_config_t cfg;
cfg.src_addr = 0x8000_0000; // 源内存地址
cfg.dst_addr = 0x9000_0000; // 目标内存地址
cfg.transfer_size = 1024; // 传输1024字节
cfg.mode = DMA_M2M; // 内存到内存模式
dma_start(&cfg); // 启动传输
小技巧:M2M传输时,建议源地址和目标地址都按4字节对齐。我曾经遇到过一个bug,就是因为地址没对齐,导致传输速度直接腰斩。
2. 内存到外设(M2P)
这个模式也很常见。CPU准备好数据放在内存里,DMA负责把这些数据喂给外设。比如你要通过UART发送一串数据,或者通过SPI输出波形。
为什么会需要M2P?因为外设通常很慢,CPU如果一直等着外设把数据吃掉,那CPU就啥也干不了了。DMA在这里扮演的角色是「快递员」——从内存取货,送到外设门口。
典型应用场景:
- UART发送数据
- SPI输出显示数据
- DAC波形输出
我记得有一次做音频播放器,需要把PCM数据送到I2S接口。如果用CPU逐字节发送,音频会卡顿。换成M2P模式后,CPU只需要把数据准备好,DMA自动搬运,音频流畅得像丝绸一样。
避坑指南:我曾经在M2P传输中忘记配置外设的请求信号,结果DMA一直不启动。记住:M2P模式下,外设必须能产生DMA请求信号,否则DMA不知道什么时候该发数据。
3. 外设到内存(P2M)
这个模式和M2P正好相反。外设产生数据,DMA负责把这些数据搬到内存里。比如ADC采样结果、UART接收的数据、摄像头采集的图像。
你想想看,如果外设每产生一个字节数据就中断CPU一次,那CPU得疯掉。P2M模式让DMA自动收集数据,攒够一定数量后再通知CPU来处理。
// P2M传输配置示例
dma_config_t cfg;
cfg.src_addr = (uint32_t)&UART->DR; // UART数据寄存器地址
cfg.dst_addr = 0x8000_1000; // 内存缓冲区
cfg.transfer_size = 256; // 接收256字节
cfg.mode = DMA_P2M; // 外设到内存模式
cfg.burst_size = 4; // 每次突发传输4字节
dma_start(&cfg);
经验之谈:P2M传输时,缓冲区大小要设置合理。太小了CPU频繁被中断,太大了可能丢失数据。我一般建议缓冲区大小是外设数据产生速率的2-3倍。
4. 外设到外设(P2P)
这个模式比较特殊,也容易被忽略。它让两个外设之间直接交换数据,完全不经过内存。比如ADC采样后直接送给DAC,或者定时器捕获信号直接触发PWM输出。
说实话,P2P模式用得不多,但在某些场景下它是神器。我曾在项目中用P2P模式实现了一个数字滤波器:ADC采集数据,DMA直接搬运到DSP模块,处理完再送到DAC。整个过程没有CPU参与,延迟极低。
P2P模式的优势:
- 延迟最小(不经过内存)
- 节省内存带宽
- 适合实时性要求高的场景
注意:P2P模式对外设的时序要求很高。我曾经在调试时发现两个外设的时钟域不同,导致数据错位。解决方案是加一个异步FIFO做缓冲,或者确保两个外设工作在同一个时钟域。
四种模式对比总结
| 传输类型 | 源端 | 目标端 | 典型应用 | 是否需要外设请求 |
|---|---|---|---|---|
| M2M | 内存 | 内存 | 数据拷贝、缓冲区刷新 | 否 |
| M2P | 内存 | 外设 | UART发送、SPI输出 | 是 |
| P2M | 外设 | 内存 | ADC采样、UART接收 | 是 |
| P2P | 外设 | 外设 | ADC到DAC、信号处理 | 是 |
核心知识体系图
下面这张图展示了四种DMA传输类型的关系和流向,我建议你仔细看看,理解数据是怎么流动的。
从这张图可以看得很清楚:M2M是内存内部搬运,M2P和P2M是内存和外设之间的双向通道,而P2P则是外设之间的直连。DMA控制器就像交通调度员,负责协调这些数据流动。
我的建议:刚开始学DMA时,先把M2M和M2P/P2M搞熟练。P2P模式可以等后面再深入研究。我在带新人时,都是让他们先从M2M开始练手,因为不需要和外设打交道,调试起来最简单。
好了,这四种传输类型就讲到这里。每种模式都有自己的用武之地,关键是要根据实际场景选择最合适的。下一节我们会深入讨论DMA的通道管理和优先级调度,到时候再聊。
公众号:蓝海资料掘金营,微信deep3321