2. DMA控制器架构:DMA通道与请求映射、源/目标地址配置、传输宽度与突发模式
DMA(Direct Memory Access)控制器是嵌入式系统中实现高速数据搬移的核心硬件模块。理解其内部架构是进行驱动隔离调试与设备移植故障排查的基础。本节将深入剖析DMA控制器的三大关键子模块:通道与请求映射、源/目标地址配置以及传输宽度与突发模式。
2.1 DMA通道与请求映射
DMA控制器通常包含多个独立的通道(Channel),每个通道可以独立配置并处理一条数据传输链路。通道是DMA引擎的基本执行单元,而请求映射(Request Mapping)则决定了哪个外设或软件事件可以触发该通道开始工作。
核心概念: 每个DMA通道都有一个专用的请求线(Request Line)。硬件设计上将外设(如UART、SPI、ADC)的DMA请求信号通过多路选择器(MUX)连接到不同的通道上。驱动开发者的任务就是正确配置这个映射关系。
下图展示了一个典型的DMA控制器内部通道与外设请求的映射架构:
调试要点: 在设备移植时,最常见的问题之一是外设请求号与DMA通道号不匹配。务必查阅芯片参考手册中的“DMA Request Mapping”表格,确认外设的DMA请求线编号。
2.2 源/目标地址配置
DMA传输的核心是数据从一个地址空间搬移到另一个地址空间。每个DMA通道都包含一组地址寄存器,用于配置源地址(Source Address)和目标地址(Destination Address)。根据传输场景,地址可以设置为固定模式或递增模式。
| 地址模式 | 描述 | 典型应用场景 |
|---|---|---|
| 固定地址 | 每次传输后地址不变,始终指向同一个寄存器或内存位置 | 外设数据寄存器(如UART_DR、SPI_DR) |
| 递增地址 | 每次传输后地址自动增加(增加量为传输宽度) | 内存缓冲区(如数组、FIFO) |
| 回环地址 | 地址递增到边界后自动回到起始地址 | 循环缓冲区(音频流、数据采集) |
地址配置的典型寄存器结构如下:
/* DMA通道地址寄存器结构(以STM32为例) */
typedef struct {
volatile uint32_t SAR; /* 源地址寄存器 (Source Address Register) */
volatile uint32_t DAR; /* 目标地址寄存器 (Destination Address Register) */
volatile uint32_t NDTR; /* 传输数据数量寄存器 (Number of Data) */
volatile uint32_t CR; /* 控制寄存器 (Control Register) */
volatile uint32_t PAR; /* 外设地址寄存器 (Peripheral Address Register) - 部分控制器 */
} DMA_Channel_TypeDef;
/* 配置示例:从外设数据寄存器读取数据到内存缓冲区 */
void dma_config_mem2mem(DMA_Channel_TypeDef *ch, uint32_t src, uint32_t dst, uint16_t size) {
ch->SAR = src; /* 源地址:外设寄存器地址 */
ch->DAR = dst; /* 目标地址:内存缓冲区地址 */
ch->NDTR = size; /* 传输数据量:字节数 */
ch->CR |= (1 << 7); /* 内存递增模式 (MINC) */
ch->CR &= ~(1 << 6); /* 外设非递增模式 (PINC = 0) */
ch->CR |= (1 << 0); /* 使能通道 (EN) */
}
常见故障: 地址对齐问题。如果源或目标地址没有按照传输宽度对齐(例如32位传输时地址不是4字节对齐),会导致总线错误(Bus Fault)或数据错位。在调试时,务必检查地址的低位对齐情况。
2.3 传输宽度与突发模式
传输宽度(Transfer Width)定义了DMA每次数据传输的位宽,通常支持字节(8位)、半字(16位)和字(32位)。突发模式(Burst Mode)则决定了DMA在获得总线控制权后,连续传输多少个数据单元。
下表对比了不同传输宽度和突发长度的组合对总线性能的影响:
| 传输宽度 | 突发长度 | 单次总线占用 | 适用场景 | 注意事项 |
|---|---|---|---|---|
| 8-bit (字节) | 1 (单次) | 1个总线周期 | 低速外设、UART | 总线利用率低 |
| 16-bit (半字) | 4 (突发) | 4个总线周期 | 音频Codec、SPI | 需外设支持突发 |
| 32-bit (字) | 8 (突发) | 8个总线周期 | 高速ADC、内存拷贝 | 可能阻塞CPU访问 |
| 32-bit (字) | 16 (增量突发) | 16个总线周期 | 显示控制器、DDR | 需FIFO深度匹配 |
突发模式的工作流程可以通过下图理解:
性能权衡:
- 单次模式: 总线延迟高,但CPU响应快,适合低数据率外设。
- 突发模式: 总线吞吐量高,但会长时间占用总线,增加CPU等待时间。在实时系统中需谨慎配置突发长度。
2.4 关键寄存器配置总结
以下表格汇总了DMA通道配置中与本节内容相关的核心寄存器位域:
| 寄存器 | 位域 | 功能描述 | 配置值示例 |
|---|---|---|---|
| CR (控制寄存器) | DIR[1:0] | 传输方向:外设到内存 / 内存到外设 / 内存到内存 | 00: 外设→内存; 01: 内存→外设; 10: 内存→内存 |
| CR | PSIZE[1:0] | 外设数据宽度:8/16/32位 | 00: 8-bit; 01: 16-bit; 10: 32-bit |
| CR | MSIZE[1:0] | 内存数据宽度:8/16/32位 | 00: 8-bit; 01: 16-bit; 10: 32-bit |
| CR | MBURST[1:0] | 内存侧突发模式:单次/4/8/16节拍 | 00: 单次; 01: 4节拍; 10: 8节拍; 11: 16节拍 |
| CR | PBURST[1:0] | 外设侧突发模式:单次/4/8/16节拍 | 00: 单次; 01: 4节拍; 10: 8节拍; 11: 16节拍 |
| SAR / DAR | [31:0] | 源/目标基地址 | 必须按PSIZE/MSIZE对齐 |
| NDTR | [15:0] | 待传输数据项数量(非字节数) | 0x0001 ~ 0xFFFF |
移植检查清单:
- 确认目标芯片的DMA通道数量与外设请求映射表。
- 检查源/目标地址是否按传输宽度对齐。
- 验证突发长度是否超出外设FIFO深度。
- 确认传输宽度设置与外设寄存器位宽一致(例如UART数据寄存器通常为8位)。