4. DMA与QSPI结合的架构设计
把DMA和QSPI连起来,不是简单拉几根线就完事。总线怎么接、请求信号怎么握手、触发条件怎么配——这三个环节但凡有一个出问题,整个传输就乱套。我见过不少工程师在这里踩坑,所以这一节我打算把架构层面的事拆开讲清楚。
4.1 系统总线连接:谁跟谁握手?
先看一张简化的系统连接图。
上图里最核心的是中间那条AHB/AXI系统总线。CPU、DMA、SRAM和QSPI全都挂在上面。实际芯片里通常还有多层总线矩阵和仲裁器。
说白了这个架构要解决两件事:谁能用总线、谁先走。DMA控制器本身是总线主设备(Master),QSPI控制器是总线从设备(Slave)。DMA要读QSPI的数据,就得仲裁得到总线权限,然后发起读传输。CPU也得让一让。
4.2 DMA请求信号:谁拉谁?
DMA不会自己跑到QSPI那边问“你有数据吗”。它靠的是QSPI主动拉一根请求线。这就是DMA请求信号(DMA Request)。
QSPI控制器通常提供两路请求:
- TX请求:发送FIFO空或低于阈值时,告诉DMA“我需要数据”。
- RX请求:接收FIFO有数据或高于阈值时,告诉DMA“你可以来取”。
请求信号的握手协议一般分几种:
| 模式 | QSPI端行为 | DMA端行为 |
|---|---|---|
| 电平触发 | 条件满足时拉高,条件消失拉低 | 检测到高电平就启动传输,传输完后自动清零 |
| 脉冲触发 | 条件满足时发出一个短脉冲(1-2周期) | 每个脉冲触发一次传输 |
| 边沿触发 | 条件满足时产生上升沿或下降沿 | 检测到边沿后启动一次传输 |
我用过的大多数MCU都是电平触发。触发后DMA会回一个应答信号(DMA Acknowledge),告诉QSPI“我开始搬了”。这一点很重要,因为在QSPI端,应答信号通常用于清除FIFO状态标志,避免重复请求。
4.3 QSPI DMA触发机制:怎么开始?
信号都接好了,接下来就是什么时候启动传输。触发机制分软件触发和硬件触发两种。多数场景用硬件触发,也就是QSPI自己拉请求线。
完整的触发流程如下:
- 初始化DMA通道:设置源地址(QSPI的数据寄存器)、目标地址(SRAM)、传输大小(字节数)和传输模式(单次/循环/散聚)。
- 使能QSPI的DMA功能:通常在QSPI控制寄存器里有一个DMAEN位,硬件会打开请求信号输出。
- 设置触发条件:比如FIFO达到某个深度(半满、全满、指定阈值)。
- 启动QSPI的读/写操作(可能是软件发送指令,或自动轮询)。
- QSPI内部产生DMA请求 → DMA控制器接到请求 → 仲裁总线 → 开始传输。
配置顺序千万别搞反。我见过有人先使能DMA再配QSPI,结果QSPI一使能就拉请求,DMA还没准备好,乱传一通。
核心顺序我建议这样:
1. 配置DMA通道参数(地址、大小、模式,但先不要使能)
2. 使能DMA通道(此时不传输,因为没有请求)
3. 配置QSPI的DMA触发条件
4. 使能QSPI的DMA请求输出
5. 启动QSPI操作(发送读指令或开启自动轮询)
这样保证DMA处于“待命”状态,QSPI一拉请求就能响。
另外还要考虑传输完成中断。DMA传输完会触发中断,通知CPU“数据已在SRAM里”,CPU可以去处理了。这时候千万别在中断里再读QSPI状态,省去不必要的延迟。
4.4 表格:不同总线拓扑对性能的影响
| 拓扑 | CPU同时访问QSPI? | DMA带宽 | 适用场景 |
|---|---|---|---|
| 单总线(AHB-lite) | 需要等待 | 最大受总线时钟限制 | 低功耗、低速系统 |
| 多层总线矩阵 | 可并行(通过不同从端口) | 无冲突时可满带宽 | 高性能、多主设备系统 |
| 带拆分传输(Split)的AHB | CPU可发起其他访问 | 中间暂停效率略降 | 支持流水线操作的复杂SoC |
你想想看,如果系统里只有一个AHB总线,DMA正在搬数据时CPU想读QSPI的寄存器,就得等DMA释放总线。所以架构设计阶段就要预估带宽,不然可能白白牺牲QSPI吞吐量。
嗯,总结一下:DMA与QSPI结合的关键是让QSPI主动请求、DMA被动响应、总线高效仲裁。你只要把这三层的配合关系吃透,后面的性能调优就有底了。