DMA专栏

DMA介绍

什么是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传输时需要设置的参数主要是:数据传输源地址数据传输目的地址传输次数每次传输的数据宽度地址是否自增,还有一些模式、方向相关参数。

模式主要就是两种:

  1. Normal: 一次传输,启用后,当传输次数为0时,DMA传输就结束了
  2. 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搬运。

image-20250804184927183

DMA1各个通道的请求映像

每个通道有一个数据选择器,选择硬件触发或者软件触发,EN 位决定数据选择器是否工作

硬件触发M2M = 0

每个外设触发通道都不一样,所以我们在选择硬件触发源时,一定要先找到对应通道触发,比如 ADC1 在通道 1,定时器更新事件 (TIM2_UP) 在通道 2

软件触发M2M = 1

DMA 和通道任意选择,每个通道软件触发都是一样的

DMA2 controller 框图

从外设(TIMx[5、6、7、8]、ADC3、SPI/I2S3、UART4、DAC通道1、2和SDIO)产生的5个请求,经逻辑或输入到DMA2控制器,其中每个通道都对应着具体的外设请求信号:

在这里插入图片描述

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个,同时为了防止内部通道拥堵,配备仲裁器,根据优先级,分配各个通道转运数据;

总框图如下:

image-20250804225437138

DMA框图:

image-20250804230739628

外设->存储器

无DMA

在没有DMA的情况下,CPU传输数据还有以内核作为中转站,比如要将ADC采集的数据转移到到SRAM中的过程是这样的:

  1. CPU通过系统总线经过总线矩阵协调,到对应的挂载到APB总线上ADC外设的ADC寄存器获取采集的数据
  2. 然后CPU再通过经过总线矩阵协调把数据放到内存SRAM中

image-20250804232513798

有DMA

  1. DMA传输时外设(SPI等)对DMA控制器发出请求。
  2. DMA控制器收到请求,触发DMA工作。
  3. DMA控制器从AHB外设获取ADC采集的数据,存储到DMA通道中
  4. DMA控制器通过DMA总线与总线矩阵协调,将数据存放到SRAM中,这个数据的传输过程中,完全不需要内核的参与,也就是不需要CPU的参与,解放CPU资源

image-20250804232854611

存储器->外设

无DMA

  1. CPU通过系统总线获取SRAM中的数据
  2. 然后再将SRAM的数据通过AHB总线送入外设寄存器(SPI数据寄存器)

image-20250804233923961

有DMA

源地址:SRAM

目的地址:SPI数据寄存器

  1. SPI发起我们的DMA请求信号。
  2. DMA控制器收到请求,触发DMA工作,DMA通过DMA总线经总线矩阵协调从SRAM中读取数据
  3. 再通过AHB总线将数据搬运到SPI数据寄存器

image-20250804234607990

DMA仲裁

当DMA发生多个DMA通道请求时,就意味着有先后响应处理的顺序问题,这个就由仲裁器管理。

仲裁器管理DMA通道请求分为两个阶段:

第一阶段属于软件阶段:可以在DMA_CCRx寄存器中设置,有4个等级:非常高、高、中和低四个优先级。

第二阶段属于硬件阶段:如果两个或以上的DMA通道请求设置的优先级相同,则他们优先级取决于通道编号,编号越低优先权越高,比如通道0高于通道1。 在大容量产品和互联型产品中, DMA1控制器拥有高于DMA2控制器的优先级。

image-20250804235114588

DMA中断

每个DMA通道都可以在DMA传输过半、传输完成和传输错误时产生中断。为应用的灵活性考虑,通过设置寄存器的不同位来打开这些中断。

在这里插入图片描述
我们可以通过查询这些标志位来获得当前 DMA 传输的状态。这里我们常用的是TCIFx位,即数据流 x的DMA传输完成与否标志。