DMA专栏

DMA专栏
THEDIDMA介绍
什么是DMA
DMA,全称Direct Memory Access,即直接存储器访问。
DMA用来提供在外设和存储器
之间或者存储器和存储器
之间的高速数据传输。无须CPU的干预,通过DMA数据可以快速地移动。这就节省了CPU的资源来做其他操作
,实现并行
的功能
我们知道CPU有转移数据、计算、控制程序转移等很多功能,系统运作的核心就是CPU,
CPU无时不刻的在处理着大量的事务,但有些事情却没有那么重要,比方说数据的复制和存储数据,如果我们把这部分的CPU资源拿出来,让CPU去处理其他的复杂计算事务,是不是能够更好的利用CPU的资源呢?
因此:转移数据(尤其是转移大量数据)是可以不需要CPU参与。比如希望外设A的数据拷贝到外设B,只要给两种外设提供一条数据通路,直接让数据由A拷贝到B不经过CPU的处理。
DMA就是基于以上设想设计的,它的作用就是解决大量数据转移过度消耗CPU资源的问题
,有了DMA使CPU更专注于更加实用的操作、计算、控制等。
DMA传输方式
DMA的作用就是实现数据的直接传输,主要涉及四种情况的数据传输,但本质上是一样的,都是从内存的某一区域
传输到内存的另一区域
(外设的数据寄存器本质上就是内存的一个存储单元)。
四种情况的数据传输如下:
- 外设到内存
- 内存到外设
- 内存到内存
- 外设到外设
DMA传输参数
DMA传输时需要设置的参数主要是:数据传输源地址
、数据传输目的地址
、传输次数
、每次传输的数据宽度
、地址是否自增
,还有一些模式、方向相关参数。
模式主要就是两种:
- Normal:
一次传输
,启用后,当传输次数为0
时,DMA传输就结束了 - Circular:
循环传输模式
,启用后,当传输次数为0
时,会恢复到最初值并重新启动DMA传输。
设置好这些参数后,就能启动DMA控制器开启数据传输
也就是说只要剩余传输数据量不是0,而且DMA是启动状态,那么就会发生数据传输。
DMA控制器
DMA请求
如果外设要想通过DMA来传输数据,必须先给DMA控制器
发送DMA请求,DMA收到请求信号之后,控制器会给外设一个应答信号, 当外设应答后且DMA控制器收到应答信号之后,就会启动DMA的传输,直到传输完毕。
DMA有DMA1和DMA2两个控制器,DMA1有7个通道,DMA2有5个通道,不同的DMA控制器的通道对应着不同的外设请求, 这决定了我们在软件编程上该怎么设置,具体见DMA请求映像表。
DMA通道
DMA具有12个独立可编程的通道,其中DMA1有7个通道,DMA2有5个通道,每个通道对应不同的外设的DMA请求。 虽然每个通道可以接收多个外设的请求,但是同一时间每个DMA Channel
只能接收一个外设请求
,不能同时接收多个。
在STM32F0/1等系列,每个通道直接和某个外设的DMA请求线绑定,而在更高级的MCU系列,升级为Stream + Channel
结构
DMA1 controller 框图
从外设(TIMx[x=1、2、3、4]、ADC1、SPI1、SPI/I2S2、I2Cx[x=1、2]和USARTx[x=1、2、3])产生的7个DMA请求,通过逻辑或输入到DMA1控制器 其中每个通道都对应着具体的外设请求信号。
DMA1控制器有7个Channel,每个Channel同一时刻只能被一个外设/请求源驱动
,但7个Channel可以并行工作,服务不同外设的DMA搬运。
每个通道有一个数据选择器,选择
硬件触发
或者软件触发
,EN 位决定数据选择器是否工作
硬件触发
:M2M = 0每个外设触发通道都不一样,所以我们在选择硬件触发源时,一定要先找到对应通道触发,比如 ADC1 在通道 1,定时器更新事件 (TIM2_UP) 在通道 2
软件触发
:M2M = 1DMA 和通道任意选择,每个通道软件触发都是一样的
DMA2 controller 框图
从外设(TIMx[5、6、7、8]、ADC3、SPI/I2S3、UART4、DAC通道1、2和SDIO)产生的5个请求,经逻辑或输入到DMA2控制器,其中每个通道都对应着具体的外设请求信号:
DMA数据流
DMA数据流仅存在于STM32F4/F7/H7等新系列,DMA控制器升级为Stream + Channel
结构:
- Stream:独立的数据搬运管道,支持并发搬运任务,数量更多(通常8个)。
- Channel:每个Stream可以选择不同外设的请求信号,配置更灵活。
数据流:
每个DMA控制器有8个数据流
,每个数据流都能够提供源
和目标
之间的单向传输链路。
每个DMA控制器可以同时配置多个数据流,但在某一时刻只允许有一个数据流
使用DMA控制器。当多个数据流同时请求时,由仲裁器
决定哪一个数据流优先使用DMA控制器。
通道:
每个数据流有8个通道
,每个通道映射到不同外设,这有利于针对不同的产品配置不同的DMA外设请求。
每个数据流
只能配置为映射到一个通道
,无法配置为映射到多个通道。即,与数据流不同,每个DMA控制器可以同时配置多个数据流(因为有仲裁器),但每个数据流不能同时配置多个通道(因为只有选择器)。
DMA工作框图
总框图介绍
ICode:指令总线,Cortex-M3内核通过ICode 总线
从Flash读取指令
(也就是CPU要执行的程序代码),
DCode:数据总线,DCode总线与Flash的数据接口相连接(用于常量加载
和调试访问)。
System:系统总线,此总线用于访问位于外设寄存器
或SRAM
中的数据。此总线访问的对象是内部SRAM、包括APB外设在内的APB1外设、APB2外设以及通过FSMC的外部存储器。
DMA总线:DMA 通过此总线来执行存储器数据的传入和传出。此总线访问的对象是数据存储器: 内部 SRAM(112 KB、64 KB、16 KB)以及通过 FSMC 的外部存储器。
总线矩阵:总线矩阵协调
内核系统总线和DMA主控总线之间的访问仲裁
,仲裁利用轮换算法
。AHB外设通过总线矩阵与系统总线相连,允许DMA访问。
**DMA内部:**DMA既是主动单元也是被动单元,挂载于在AHB总线
上,CPU可通过AHB控制读写DMA配置寄存器,DMA1内部有7个可配置通道,DMA2有5个,同时为了防止内部通道拥堵,配备仲裁器,根据优先级,分配各个通道转运数据;
总框图如下:
DMA框图:
外设->存储器
无DMA
在没有DMA的情况下,CPU传输数据还有以内核作为中转站,比如要将ADC采集的数据转移到到SRAM中的过程是这样的:
- CPU通过系统总线经过总线矩阵协调,到对应的挂载到APB总线上ADC外设的ADC寄存器获取采集的数据
- 然后CPU再通过经过总线矩阵协调把数据放到内存SRAM中
有DMA
- DMA传输时外设(SPI等)对DMA控制器发出请求。
- DMA控制器收到请求,触发DMA工作。
- DMA控制器从AHB外设获取ADC采集的数据,存储到DMA通道中
- DMA控制器通过
DMA总线
与总线矩阵协调,将数据存放到SRAM中,这个数据的传输过程中,完全不需要内核的参与,也就是不需要CPU的参与,解放CPU资源
存储器->外设
无DMA
- CPU通过系统总线获取SRAM中的数据
- 然后再将SRAM的数据通过AHB总线送入外设寄存器(SPI数据寄存器)
有DMA
源地址
:SRAM
目的地址
:SPI数据寄存器
- SPI发起我们的DMA请求信号。
- DMA控制器收到请求,触发DMA工作,DMA通过DMA总线经总线矩阵协调从SRAM中读取数据
- 再通过AHB总线将数据搬运到SPI数据寄存器
DMA仲裁
当DMA发生多个DMA通道请求时,就意味着有先后响应处理的顺序问题,这个就由仲裁器管理。
仲裁器管理DMA通道请求分为两个阶段:
第一阶段属于软件
阶段:可以在DMA_CCRx寄存器中设置,有4个等级:非常高、高、中和低四个优先级。
第二阶段属于硬件
阶段:如果两个或以上的DMA通道请求设置的优先级相同
,则他们优先级取决于通道编号,编号越低优先权越高
,比如通道0高于通道1。 在大容量产品和互联型产品中, DMA1控制器拥有高于DMA2控制器的优先级。
DMA中断
每个DMA通道都可以在DMA传输过半、传输完成和传输错误时产生中断。为应用的灵活性考虑,通过设置寄存器的不同位来打开这些中断。
我们可以通过查询这些标志位来获得当前 DMA 传输的状态。这里我们常用的是TCIFx位,即数据流 x的DMA传输完成与否标志。