首页
找靠谱产品
找解决方案
找靠谱公司
找案例
找对的人
专家智库
悬赏任务
SAAS
ToB门户
了解全球最新的ToB事件
论坛
潜水/灌水快乐,沉淀知识,认识更多同行。
ToB圈子
加入IT圈,遇到更多同好之人。
微博
Follow
记录
Doing
博客
Blog
文库
业界最专业的IT文库,上传资料也可以赚钱
下载
分享
Share
排行榜
Ranklist
相册
Album
应用中心
qidao123.com ToB IT社区-企服评测·应用市场
»
论坛
›
虚拟化.超融合.云计算
›
公有云
›
SAAS
›
从 DREQ 到制止:RP2040 DMA 的 “快递系统” 全解析 ...
返回列表
发新帖
从 DREQ 到制止:RP2040 DMA 的 “快递系统” 全解析
[复制链接]
发表于 2026-7-28 18:01:33
|
显示全部楼层
|
阅读模式
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要
登录
才可以下载或查看,没有账号?
立即注册
×
DMA
内核的本职是 “运算、处理使命”,如果让它手动搬数据(好比从传感器读数据存到内存),会浪费算力(搬数据时没法干别的);而 DMA 是 “专职搬运工具”,能高效完成批量传输,让内核可以去处理其他使命,甚至进入低功耗休眠,既提升效率又节省电量。
DMA 直接存储器存取控制器与总线结构有单独的读和写主连接,并可以代替处理器实行批量数据传输。这使得处理器可以自由地处理其他使命,或进入低功耗睡眠状态。
DMA 单独读写最多可以操控 32 位数据,具有 12 个独立的通道,每个通道都监督一系列总线传输。
DMA 通常用于以下三种情况的数据传输:
内存到外设:
当必要更多数据时,外设向 DMA 发出信号。DMA 从 RAM 或 flash 中的数组中读取数据,并写入外围设备的数据 FIFO;
外设到内存:
当一个外围设备在接收到外部的传感器/通讯接口的数据时,它就会向 DMA 发出信号。DMA 从外围设备的数据 FIFO 中读取这些数据,并将其写入 RAM 中的一个数组;
内存到内存:
DMA 在 RAM 中的两个缓冲区之间传输数据。
图 2.17 RP2040 DMA 控制器架构框图
架构图是 DMA 的 “内部工作流程”,每个模块的作用如下:
AHB-lite Read/Write Master 总线:
是 DMA 连接到系统总线(AHB-lite)的 “接口:
Read Master:负责从系统(内存 / 外设)读数据;
Write Master:负责向系统(内存 / 外设)写数据。
Read/Write Address FIFO:
FIFO 是 “先进先出的缓冲区”,这里存的是要读取 / 写入的地址(好比从内存的 0x20000000 开始传输,地址会存在这里)。它可以地址请求,制止地址生成和数据传输 “节奏不匹配” 导致卡顿。
Transfer Data FIFO:
它存的是正在传输的数据,同样是缓冲作用,让 “地址请求” 和 “数据搬运” 的节奏对齐,保证传输流畅。
Address Generator:
DMA 的 “地址自动计算器”:好比要从内存的 0x20000000 开始,连续传 100 个字节,它会自动生成 0x20000000、0x20000001… 这些连续地址,不用内核手动算地址。
Control/Status Registers:
是 DMA 的控制中心 + 状态表现器:
控制:软件通过这里配置 DMA(好比传输方向是 “外设 → 内存” 还是 “内存 → 外设”、数据大小是 8/16/32 位、要传多少数据);
状态:软件可以在这里查看传输进度(好比传了多少、有没有传完、有没有堕落)。
AHB-lite Slave Interface:
是 “内核配置 DMA 的入口”:内核通过这个接口,向 Control/Status Registers 写入配置参数,告诉 DMA“要搬什么数据、怎么搬”。
接下来,我们以 “外设 → 内存” 传输(好比传感器数据存到内存)为例:
内核通过
AHB-lite Slave Interface
,给 Control/Status Registers 写配置(好比源地址是传感器的 FIFO 地址、目标地址是内存数组地址、传输长度是 100 字节);
Address Generator
自动生成要读取的外设地址、要写入的内存地址,分别存到 Read Address FIFO、Write Address FIFO;
AHB-lite Read Master
从外设读数据,放到 Transfer Data FIFO 缓冲;
AHB-lite Write Master
从 Transfer Data FIFO 取数据,写到内存的目标地址;
整个过程中,内核不用参与,完全由 DMA 自动完成。
DMA的每个通道都有对应状态寄存器,软件可以通过它来编程和监控该通道数据读写的进度。
我们把每个 DMA 通道想象成一个独立的快递小哥,而状态寄存器就是这个小哥的 “使命清单 + 工作日志本”:
编程(写寄存器)
:你(软件)在小哥出发前,把使命写在日志本上 —— 好比 “从内存的 A 位置搬 100 个数据到 UART 外设”“搬数据时要听 UART 的 DREQ 信号指挥”,这就是给 DMA 通道配置使命;
监控进度(读寄存器)
:小哥干活时,会实时在日志本上记录进度 ——“已搬了 50 个数据”“使命完成”“搬数据时堕落了”,你(软件)随时看日志本,就能知道这个 DMA 通道的工作状态,不用一直盯着它干活。
DMA 传输数据的大小可以是 32、16 或 8 位。每个通道配置一次:源传输大小和目标传输大小相同:
这是规定了 DMA “搬数据的打包方式”——DMA 每次搬数据时,可选择搬
1 个字节(8 位)、2 个字节(16 位)或 4 个字节(32 位)
(相当于快递小哥一次搬 1 个包裹、2 个包裹或 4 个包裹);
源和目标大小必须相同
:意思是 “从哪里搬” 和 “搬到哪里去” 的打包方式要一致 —— 不能从内存里一次搬 4 个字节(32 位),却往外设里一次只写 1 个字节(8 位),否则会出现数据庞杂(就像小哥一次抱 4 个包裹,却只能往快递柜里塞 1 个,剩下的会掉地上);
每个通道配置一次
:一个 DMA 通道一旦定了用 32 位传输,那这次使命全程都用 32 位,不用中途改;要换方式的话,得重新配置这个通道。
DMA 不同通道之间可以相互组合,例如一个通道可以配置另一个通道,从内存中的一系列控制块加载配置数据,然后当必要重新配置时,第二个通道可以通过 CHAIN_TO 选项调用到第一通道:
这是 DMA 通道的 “接力干活” 或 “互相配合” 功能,让多个 DMA 通道能协同完成复杂使命,不用软件(内核)中途插手;
假设你有两个 DMA 通道,
通道 1
是 “配置员”,
通道 2
是 “搬运工”:
你先在内存里存好
多套搬运使命的配置
(好比 “使命 1:搬 100 个 32 位数据到 UART0”“使命 2:搬 200 个 8 位数据到 SPI0”“使命 3:把内存 A 的数据复制到内存 B”),这些配置叫 “控制块”。
你给通道 2 配置初始使命:“先找通道 1,让它从内存里读第一套控制块(使命 1),然后按这个控制块干活”。
当通道 2 完成使命 1 后,不必要软件(内核)来重新配置,它可以通过
CHAIN_TO 选项
(相当于 “呼唤接力”),让通道 1 再从内存里读第二套控制块(使命 2),然后通道 2 继承干使命 2;以此类推,直到所有控制块的使命都完成。
同时 DMA 也可以和其他外设配合使用,外设和 DMA 直接通过 DREQs 通道传输,所谓 DREQ,就是外设给 DMA 发的“暗号”,告诉 DMA“我准备好收 / 发数据了,你可以开始传了”:
好比 UART 要发数据时:当 UART 的发送 FIFO 空了,它会发 DREQ 信号给 DMA,DMA 收到后就把内存里的数据传到 UART 的 FIFO;
好比 UART 要收数据时:当 UART 的接收 FIFO 满了,它发 DREQ 给 DMA,DMA 就把 FIFO 里的数据取到内存。
不同外设和 DREQ 通道对应关系可以查看 DREQ 表,它是“外设功能 →DREQ 通道” 的对应清单,每个 DREQ 编号对应一个外设的收 / 发功能:
图 2.18 RP2040 外设 DREQ 通道与 DMA 映射表
以上表为例,我们可以看到:
DREQ20 对应 “UART0_TX”(UART0 的发送请求);
DREQ17 对应 “SPI0_RX”(SPI0 的接收请求)。
DMA 也可以和制止配合使用,当 DMA 中某个通道数据读写完成后可以触发制止,使得步伐进行对应操作(好比数据传完了,内核去分析这些数据):
咱们把 DMA 通道比作
负责不同搬运使命的快递小哥
,内核就是公司里的 “老板”;
之前说过,小哥干活的时间,老板可以摸鱼(处理其他使命)或者睡觉(低功耗休眠),不用盯着小哥;
当小哥把一批数据搬完了(好比把传感器的 100 个数据全存到内存里了),他不能直接跑去找老板 —— 而是会按一个 “紧急呼唤铃”,这个
呼唤铃就是制止
;
老板听到铃响,就知道 “某个小哥的活干完了”,然后放下手里的事,去做后续工作(好比分析刚搬来的传感器数据、把数据再传给 U 盘、清空内存准备下一次搬运)。
简单说,
DMA 完成使命后触发制止,是给内核发 “完工关照”
,让内核能及时处理后续使命,不用一直轮询 “DMA 干完没?干完没?”,既省了内核的精力,又保证了使命的及时性。
RP2040 DMA 提供了两个系统 IRQs,具有独立的掩蔽和状态寄存器(例如,INTE0、INTE1)。任何通道制止请求的组合都可以被路由到任何一个系统 IRQ:
先解释这段话里的关键名词,再用例子串起来:
系统 IRQs
:可以理解成公司里的
两个 “总客服热线”
(IRQ0 和 IRQ1,对应 INTE0、INTE1),所有 DMA 小哥的 “完工关照”(制止请求),都要通过这两个热线打给老板(内核)。
掩蔽寄存器
:“掩蔽” 就是 “屏蔽、静音” 的意思,这个寄存器相当于热线的 “静音开关”—— 好比你可以设置 “让小哥 1 的关照打不进热线 0”,或者 “让热线 1 暂时静音,所有关照都走热线 0”,制止不重要的关照打扰老板。
状态寄存器
:相当于热线的 “来电记录本”,里面会记着 “是小哥 3 的关照打进来了”“小哥 7 的使命完工了”,老板看到记录本,就知道该处理哪个小哥的后续使命。
路由
:就是 “分配、定向” 的意思 —— 你可以任意安排哪个小哥的关照走哪个热线。
RP2040 的 DMA 有 12 个通道(12 个小哥),但只留了 2 个客服热线(两个系统 IRQs)。你可以这样配置:
把
小哥 1(传感器数据搬运)、小哥 2(UART 数据传输)的关照,都路由到热线 0(INTE0)
;
把
小哥 3(内存复制)、小哥 4(SPI 数据传输)的关照,都路由到热线 1(INTE1)
;
甚至可以把所有小哥的关照都路由到同一个热线,或者让某几个小哥的关照同时走两个热线;
如果你觉得小哥 3 的使命不重要,还能通过掩蔽寄存器,把小哥 3 的关照屏蔽掉,他就算完工了,也打不进热线,老板不会收到他的关照。
这种设计的好处是:
机动管理多个 DMA 通道的制止,制止制止信号杂乱,同时让内核可以按热线的优先级处理不同范例的 DMA 使命
(好比把紧急的使命路由到优先级高的热线)。
回复
使用道具
举报
返回列表
浏览过的版块
Oracle
程序人生
SQL-Server
Java
Nosql
DevOps与敏捷开发
.Net
物联网
开源技术
愛在花開的季節
+ 我要发帖
登录后关闭弹窗
登录参与点评抽奖 加入IT实名职场社区
去登录
微信订阅号
微信服务号
微信客服(加群)
H5
小程序
快速回复
返回顶部
返回列表