在嵌入式系统设计中,DMA(Direct Memory Access)技术如同一位高效的物流主管,它能绕过CPU直接在外设和内存之间搬运数据。以ARM架构为例,其DMA控制器(DMAC)通过精心设计的信号握手协议实现这一过程。让我们拆解这个精密的数据传输引擎。
DMACREQx(DMA请求信号) 是数据传输的发起者。当外设准备好进行DMA传输时,会拉高这个信号,相当于按下"开始按钮"。关键特性包括:
DMACCLRx(DMA清除信号) 是控制器的应答信号,相当于"任务完成"指示灯:
c复制// 典型握手流程伪代码
while(DMACREQx == HIGH) {
if(DMACCLRx == HIGH) {
DMACREQx = LOW; // 外设收到应答后撤销请求
}
}
DMACTCx(终端计数信号) 标记数据包传输结束,常用于流控制场景。例如在音频处理中,当DMA传输完一个音频帧后会触发此信号,通知编解码器进行后续处理。
当外设与DMAC处于不同时钟域时,需要特殊的同步处理。ARM提供了优雅的解决方案:
警告:绝对禁止在DMACCLRx为高时发起新的请求,这会导致总线协议冲突。实际项目中我曾因此导致整个视频采集系统死锁,最终通过逻辑分析仪捕获到该违规时序。
图B-23展示的典型时序包含三个关键阶段:
突发传输长度由AHB总线HSIZE[2:0]和HBURST[2:0]信号共同决定。例如配置为INCR4(4拍递增突发)时,单次传输可搬运4×32bit=16字节数据。
图B-24揭示了DMA传输与AHB总线的协同工作细节:
| AHB信号 | 作用描述 | 典型配置值 |
|---|---|---|
| HTRANS[1:0] | 传输类型指示 | 2'b10表示连续传输 |
| HADDR[31:0] | 32位地址总线 | 按传输粒度递增 |
| HWDATA[31:0] | 写数据总线 | 外设→内存时有效 |
| HRDATA[31:0] | 读数据总线 | 内存→外设时有效 |
突发传输期间,地址生成器会根据HSIZE自动递增:
在复杂数据传输场景中(如视频处理),内存中的数据往往非连续存储。ARM DMA通过LLI实现智能搬运:
c复制typedef struct {
uint32_t src_addr; // 源地址
uint32_t dst_addr; // 目标地址
uint32_t ctrl; // 控制字(包含传输长度、突发大小等)
uint32_t next_lli; // 下一个LLI地址(0表示结束)
} DMA_LLI;
典型配置示例:
armasm复制LDR R0, =0x20000 ; LLI表基址
LDR R1, =0x0A200 ; 源地址
STR R1, [R0], #4 ; 存储src_addr
LDR R1, =Periph_Addr ; 外设地址
STR R1, [R0], #4 ; 存储dst_addr
LDR R1, =0x0000C006 ; 控制字:长度0xC00,突发16
STR R1, [R0], #4
LDR R1, =0x20010 ; 下一个LLI地址
STR R1, [R0], #4
在异构系统中,外设时钟(如SPI的25MHz)常与AHB总线时钟(如100MHz)不同步。未正确同步时会出现:
硬件同步:
软件容错:
c复制void DMA_Start_Safe(DMA_Channel_TypeDef *ch) {
ch->CFG |= DMA_CFG_EN;
__DSB(); // 确保配置完成
while(!(ch->RAWINTSTAT & DMA_RAWINTSTAT_ACTIVE));
}
时序余量计算:
同步所需最小时钟周期数 =
⌈(Tclk_src + Tclk_dest + Tsu)/Tclk_dest⌉ + 2
其中Tsu为建立时间要求
通过实测数据对比不同配置的性能差异:
| 突发长度 | 传输1KB耗时(cycles) | 总线利用率 |
|---|---|---|
| 单次传输 | 1024 | 35% |
| INCR4 | 320 | 68% |
| INCR8 | 160 | 82% |
| INCR16 | 88 | 91% |
优化建议:
在音频流处理中,采用双LLI结构实现无缝数据传输:
c复制void Setup_PingPong_Buffers(void) {
// Ping缓冲区LLI
LLI_Ping.next_lli = (uint32_t)&LLI_Pong;
// Pong缓冲区LLI
LLI_Pong.next_lli = (uint32_t)&LLI_Ping;
DMA->CH[0].LLI = (uint32_t)&LLI_Ping;
Enable_IRQ(DMA_IRQn); // 启用传输完成中断
}
中断服务程序中只需刷新下一块缓冲区数据即可维持连续传输,实测延迟可降低至单缓冲方案的1/3。
当DMA传输出现异常时,建议按以下顺序排查:
问题现象:DMA传输随机中断
问题现象:吞吐量不达标
在多年的项目实践中,我发现约70%的DMA问题源于时钟域交叉和内存对齐问题。建议在初期设计时就加入足够的时序余量和错误检测机制。