2、DMA基础回顾:DMA的工作原理、传输模式(内存到内存、外设到内存)、与CPU中断的对比
在TinyML系统中,传感器数据采集、音频流处理、运动检测等场景对实时性和功耗有着严苛要求。若所有数据搬运都依赖CPU逐字节处理,不仅会大量占用CPU周期,还会因频繁进出中断服务程序而引入不可控的延迟抖动。DMA(Direct Memory Access,直接存储器访问)正是为解决这一瓶颈而设计的硬件机制。本章将系统梳理DMA的核心工作原理、两种关键传输模式,并通过与中断机制的深度对比,帮助你在TinyML工程中做出正确的数据通路设计决策。
2.1 DMA核心工作原理:谁在搬运数据?
DMA的本质是一种硬件数据搬运引擎。当CPU配置好DMA控制器后,DMA便独立于CPU,直接在内存与外设之间、或内存的不同区域之间传输数据。整个传输过程由DMA控制器内部的有限状态机(FSM)管理,无需CPU逐条指令干预。
一个典型的DMA传输周期包含以下阶段:
- 请求阶段:外设(如ADC完成一次采样)或软件置位DMA请求标志,DMA控制器检测到请求后向总线仲裁器申请总线控制权。
- 应答阶段:总线仲裁器在CPU不访问总线的时间隙(或通过周期窃取方式)将总线控制权交给DMA控制器。
- 传输阶段:DMA控制器按照配置的源地址、目的地址、传输宽度(8/16/32位)和传输计数,执行一次或突发(Burst)多次数据传输。
- 地址更新与计数递减:每次传输后,DMA自动更新源/目的地址(递增、递减或固定),并将剩余传输计数减一。
- 完成判断:当计数减至零,DMA置位传输完成标志,并可触发中断通知CPU。
在TinyML场景中,DMA的典型应用是连续采集传感器数据到双缓冲区。例如,一个100Hz的IMU数据流,每个样本6字节(3轴×2字节),DMA可以配置为每采集10个样本触发一次中断,而CPU在中断中仅处理已填满的缓冲区,另一缓冲区继续由DMA填充,实现采集与计算的重叠。
关键参数速查表:配置DMA时必须明确的五个要素
| 参数 | 说明 | TinyML典型值 |
|---|---|---|
| 源地址 | 数据来源(外设数据寄存器或内存地址) | ADC->DR 或 &buffer[0] |
| 目的地址 | 数据去向(内存地址或外设寄存器) | &dma_buffer[0] |
| 传输宽度 | 每次搬运的数据位宽 | 8位(麦克风PCM)/ 16位(加速度计) |
| 传输计数 | 总共搬运的数据单元数 | 160(对应20ms音频帧) |
| 循环模式 | 是否自动回绕形成环形缓冲区 | 通常开启,用于连续采集 |
2.2 两种核心传输模式:内存到内存与外设到内存
根据数据源和目的地的不同,DMA传输模式可分为两大类,它们在TinyML工作负载中扮演不同角色。
2.2.1 内存到内存(Memory-to-Memory)模式
该模式下,DMA在内存的两个区域之间搬运数据,无需外设参与。CPU只需设置源地址、目的地址和传输长度,DMA便完成剩余工作。在TinyML中,这种模式常用于:
- 数据预处理:将传感器原始数据从采集缓冲区搬运到对齐的推理输入缓冲区。
- 特征重排:将非连续存储的特征数据整理为连续内存块,便于向量处理器或SIMD指令高效访问。
- 模型权重加载:从Flash读取权重到SRAM(部分MCU支持Flash到SRAM的DMA传输)。
需要注意的是,内存到内存模式会持续占用总线,因此传输期间CPU可能因总线竞争而变慢。在实时性要求高的推理阶段,应避免大块内存拷贝与推理计算同时进行。
2.2.2 外设到内存(Peripheral-to-Memory)模式
这是TinyML中最常用的DMA模式。外设(如ADC、I2S、UART)在接收到数据后,通过硬件请求线通知DMA控制器,DMA将外设数据寄存器中的内容搬运到指定的内存缓冲区。该模式的优势在于:
- 零CPU干预采集:CPU可以进入低功耗模式或执行其他计算,直到缓冲区填满。
- 精确的采样时序:由外设触发DMA传输,保证采样间隔的确定性,不受中断延迟影响。
- 支持突发传输:当FIFO积累一定数据后,DMA可以一次突发搬运多个数据,提高总线利用率。
以音频采集为例:I2S接口以16kHz采样率持续产生16位PCM数据,DMA配置为循环模式,每采集320个样本(20ms帧)触发一次中断。CPU在中断中处理当前帧,而DMA继续采集下一帧,实现无缝音频流处理。
工程经验:在配置外设到内存DMA时,务必确认外设的DMA请求映射关系。例如,STM32系列中ADC1的DMA请求可能映射到DMA1的Channel1,而I2S2则映射到DMA1的Channel4。错误的映射会导致数据错乱或DMA无法启动。
2.3 DMA与CPU中断的深度对比:何时用谁?
中断和DMA都是解决CPU与外设速度不匹配的机制,但它们的定位截然不同。中断是事件通知机制,DMA是数据搬运机制。下表从多个维度进行对比:
| 对比维度 | DMA | CPU中断 |
|---|---|---|
| 数据搬运主体 | 专用硬件控制器 | CPU执行中断服务程序(ISR) |
| CPU占用 | 配置完成后几乎为零 | 每次中断都需保存/恢复现场 |
| 实时性 | 硬件级响应,纳秒级启动 | 受中断优先级和嵌套影响,微秒级 |
| 批量传输效率 | 极高,支持突发传输 | 低,逐字节搬运浪费总线带宽 |
| 功耗影响 | CPU可进入睡眠模式 | CPU必须频繁唤醒 |
| 适用场景 | 高频、大批量、周期性数据 | 低频事件、控制命令、异常处理 |
| 配置复杂度 | 较高(需初始化DMA通道) | 较低(仅设置中断向量和优先级) |
在实际TinyML系统中,两者通常协同工作而非互斥。典型模式是:DMA负责数据搬运,传输完成时触发一个中断,CPU在中断中仅做轻量级处理(如切换缓冲区指针、触发推理任务),而非逐字节读取数据。这种设计将CPU从繁重的数据搬运中解放出来,使其专注于推理计算和系统控制。
2.4 案例拆解:基于DMA的麦克风音频采集与推理触发
下面通过一个具体的TinyML语音唤醒词检测场景,展示DMA如何与外设采集、缓冲更新和推理触发协同工作。
系统背景与约束:
- MCU:Cortex-M4F @ 80MHz,内置64KB SRAM
- 音频输入:数字麦克风通过I2S接口,16kHz采样率,16位单声道
- 推理模型:关键字识别模型,输入为20ms音频帧(320个样本),推理耗时约15ms
- 功耗目标:平均电流<1mA(含传感器和MCU)
初始方案与问题:最初采用中断方式采集音频,每次I2S接收FIFO半满(16个样本)触发一次中断,CPU在ISR中读取数据并存入缓冲区。实测发现:
- CPU在ISR中耗时约8μs,中断频率为1000Hz(16kHz/16),CPU占用率达10%
- 频繁的中断导致推理任务被抢占,推理延迟抖动达到±3ms
- CPU无法进入睡眠模式,平均功耗高达2.3mA
DMA方案设计与实施:
- 配置DMA1 Channel4:源地址为I2S2_DATA_DR,目的地址为audio_buf[0],传输宽度16位,传输计数320,循环模式开启。
- 配置双缓冲区:audio_buf[0]和audio_buf[1]各320样本(640字节),DMA交替填充。
- 使能DMA传输完成中断:当DMA填满一个缓冲区并切换到另一个时,触发中断。
- 中断服务程序精简:ISR中仅做两件事——切换当前活动缓冲区指针,并设置一个标志位通知主循环执行推理。
- 主循环处理:检测到标志位后,从已填满的缓冲区拷贝数据到推理输入(或直接使用DMA缓冲区地址),执行推理。
结果对比与复盘:
| 指标 | 中断方案 | DMA方案 | 改善幅度 |
|---|---|---|---|
| CPU占用率 | 10% | 1.5% | ↓85% |
| 推理延迟抖动 | ±3ms | ±0.2ms | ↓93% |
| 平均功耗 | 2.3mA | 0.8mA | ↓65% |
| 代码复杂度 | 简单 | 中等(需配置DMA) | 可接受 |
风险与代价:DMA配置错误可能导致数据错位或总线冲突;双缓冲区需要额外640字节SRAM(占总SRAM的1%);调试DMA时序问题比中断更复杂,需要逻辑分析仪辅助。
常见误区提醒:
- 误区1:认为DMA传输完成后数据立即可用。实际上,需要等待DMA完全停止(或使用内存屏障指令)后再访问缓冲区,否则可能读到不一致数据。
- 误区2:忽略DMA传输宽度与外设寄存器位宽匹配。例如,16位外设配置为8位DMA传输会导致数据错位。
- 误区3:在DMA传输过程中修改缓冲区地址或计数。这会导致未定义行为,应在DMA禁用状态下重新配置。
- 误区4:认为DMA可以完全替代中断。DMA完成仍需中断通知CPU,且错误处理(如FIFO溢出)仍需中断介入。
2.5 总结与设计决策建议
DMA是TinyML系统中实现高效数据通路的核心硬件资源。选择DMA还是中断,应基于以下判断路径:
- 数据速率 > 1kHz且每次传输数据量 > 4字节:优先考虑DMA。
- 需要精确的采样间隔或低功耗运行:必须使用DMA,使CPU尽可能睡眠。
- 事件频率低(<100Hz)且处理逻辑简单:中断即可满足需求,避免DMA配置开销。
- 混合场景:使用DMA搬运数据,中断仅做事件通知,两者协同。