4. DMA与QSPI结合的架构设计

把DMA和QSPI连起来,不是简单拉几根线就完事。总线怎么接、请求信号怎么握手、触发条件怎么配——这三个环节但凡有一个出问题,整个传输就乱套。我见过不少工程师在这里踩坑,所以这一节我打算把架构层面的事拆开讲清楚。

4.1 系统总线连接:谁跟谁握手?

先看一张简化的系统连接图。

DMA与QSPI系统总线连接示意 AHB / AXI 系统总线 CPU / 核心 DMA 控制器 SRAM / 内存 QSPI 控制器 外部 Flash DMA请求 注意:DMA请求信号由QSPI发出,经总线桥接到DMA控制器,不直接走AHB总线本身的地址通道。

上图里最核心的是中间那条AHB/AXI系统总线。CPU、DMA、SRAM和QSPI全都挂在上面。实际芯片里通常还有多层总线矩阵和仲裁器。

说白了这个架构要解决两件事:谁能用总线、谁先走。DMA控制器本身是总线主设备(Master),QSPI控制器是总线从设备(Slave)。DMA要读QSPI的数据,就得仲裁得到总线权限,然后发起读传输。CPU也得让一让。

一个小经验: 我在某个项目里遇到QSPI读取偶尔丢数据,排查发现是DMA和CPU同时争抢总线,仲裁器把CPU优先级设低了,结果CPU中断响应被延迟。后来我把DMA传输安排在IDLE周期里,问题才解决。总线冲突不是玄学,是真坑。

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状态标志,避免重复请求。

我曾经… 踩过一个坑:某款芯片的QSPI在接收到DMA应答后,会立即把接收FIFO中的数据清掉。如果DMA实际读走的字节数和FIFO中残留的不匹配,数据就丢了。解决办法是确保DMA传输长度和QSPI预期的FIFO深度一致。

4.3 QSPI DMA触发机制:怎么开始?

信号都接好了,接下来就是什么时候启动传输。触发机制分软件触发和硬件触发两种。多数场景用硬件触发,也就是QSPI自己拉请求线。

完整的触发流程如下:

  1. 初始化DMA通道:设置源地址(QSPI的数据寄存器)、目标地址(SRAM)、传输大小(字节数)和传输模式(单次/循环/散聚)。
  2. 使能QSPI的DMA功能:通常在QSPI控制寄存器里有一个DMAEN位,硬件会打开请求信号输出。
  3. 设置触发条件:比如FIFO达到某个深度(半满、全满、指定阈值)。
  4. 启动QSPI的读/写操作(可能是软件发送指令,或自动轮询)。
  5. 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吞吐量。

一个小技巧: 如果平台支持,可以把QSPI的配置寄存器挂在APB桥上(非DMA路径),而数据寄存器映射到AHB的高速地址空间。这样CPU读写配置不占用主总线带宽,DMA读数据时不受干扰。

嗯,总结一下:DMA与QSPI结合的关键是让QSPI主动请求、DMA被动响应、总线高效仲裁。你只要把这三层的配合关系吃透,后面的性能调优就有底了。