dma 订阅
DMA(Direct Memory Access,直接存储器访问) 是所有现代电脑的重要特色,它允许不同速度的硬件装置来沟通,而不需要依赖于 CPU 的大量中断负载。否则,CPU 需要从来源把每一片段的资料复制到暂存器,然后把它们再次写回到新的地方。在这个时间中,CPU 对于其他的工作来说就无法使用。 展开全文
DMA(Direct Memory Access,直接存储器访问) 是所有现代电脑的重要特色,它允许不同速度的硬件装置来沟通,而不需要依赖于 CPU 的大量中断负载。否则,CPU 需要从来源把每一片段的资料复制到暂存器,然后把它们再次写回到新的地方。在这个时间中,CPU 对于其他的工作来说就无法使用。
信息
功    能
不同速度的硬件装置来沟通
外文名
Direct Memory Access
缩    写
DMA
来    源
嵌入式底层驱动
中文名
直接存储器访问
DMA原理
DMA 传输将数据从一个地址空间复制到另外一个地址空间。当CPU 初始化这个传输动作,传输动作本身是由 DMA 控制器来实行和完成。典型的例子就是移动一个外部内存的区块到芯片内部更快的内存区。像是这样的操作并没有让处理器工作拖延,反而可以被重新排程去处理其他的工作。DMA 传输对于高效能 嵌入式系统算法和网络是很重要的。 在实现DMA传输时,是由DMA控制器直接掌管总线,因此,存在着一个总线控制权转移问题。即DMA传输前,CPU要把总线控制权交给DMA控制器,而在结束DMA传输后,DMA控制器应立即把总线控制权再交回给CPU。一个完整的DMA传输过程必须经过DMA请求、DMA响应、DMA传输、DMA结束4个步骤。CPU对DMA控制器初始化,并向I/O接口发出操作命令,I/O接口提出DMA请求。DMA控制器对DMA请求判别优先级及屏蔽,向总线裁决逻辑提出总线请求。当CPU执行完当前总线周期即可释放总线控制权。此时,总线裁决逻辑输出总线应答,表示DMA已经响应,通过DMA控制器通知I/O接口开始DMA传输。DMA控制器获得总线控制权后,CPU即刻挂起或只执行内部操作,由DMA控制器输出读写命令,直接控制RAM与I/O接口进行DMA传输。在DMA控制器的控制下,在存储器和外部设备之间直接进行数据传送,在传送过程中不需要中央处理器的参与。开始时需提供要传送的数据的起始位置和数据长度。当完成规定的成批数据传送后,DMA控制器即释放总线控制权,并向I/O接口发出结束信号。当I/O接口收到结束信号后,一方面停 止I/O设备的工作,另一方面向CPU提出中断请求,使CPU从不介入的状态解脱,并执行一段检查本次DMA传输操作正确性的代码。最后,带着本次操作结果及状态继续执行原来的程序。由此可见,DMA传输方式无需CPU直接控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为RAM与I/O设备开辟一条直接传送数据的通路,使CPU的效率大为提高。
收起全文
精华内容
下载资源
问答
  • DMA

    千次阅读 多人点赞 2018-08-13 19:17:02
    DMA(Direct Memory Access,直接内存存取) DMA 传输将数据从一个地址空间复制到另外一个地址空间。当CPU 初始化这个传输动作,传输动作本身是由 DMA 控制器来实行和完成。典型的例子就是移动一个外部内存的区块到...

    DMA(Direct Memory Access,直接内存存取)

    DMA 传输将数据从一个地址空间复制到另外一个地址空间。当CPU 初始化这个传输动作,传输动作本身是由 DMA 控制器来实行和完成。典型的例子就是移动一个外部内存的区块到芯片内部更快的内存区。像是这样的操作并没有让处理器工作拖延,反而可以被重新排程去处理其他的工作。DMA 传输对于高效能 嵌入式系统算法和网络是很重要的。

    DMADMA

    在实现DMA传输时,是由DMA控制器直接掌管总线,因此,存在着一个总线控制权转移问题。即DMA传输前,CPU要把总线控制权交给DMA控制器,而在结束DMA传输后,DMA控制器应立即把总线控制权再交回给CPU。一个完整的DMA传输过程必须经过DMA请求、DMA响应、DMA传输、DMA结束4个步骤。

    DMA方式是一种完全由硬件进行组信息传送的控制方式。具有程序中断方式的优点,即在数据准备阶段,CPU与外设并行工作。DMA方式在外设与内存之间开辟一条“直接数据通路”,信息传送不再经过CPU,降低了CPU在传送数据时的开销,因此称为直接存储器存取方式,由于数据传送不再经过CPU,也就不需要保护、恢复CPU现场等繁琐操作。

    这种方式适用于磁盘机、磁带机等高速设备大批量数据的传送,它的硬件开销比较大,在DMA方式中,中断的作用仅限于故障和正常传送结束时的处理。

     1.DMA方式的特点

    主存和DMA接口之间有一条直接数据通路。由于DMA方式传送数据不需要经过CPU,因此不必中断现行程序,I/O与主机并行工作,程序和传送并行工作。

    DMA方式具有下列特点:
    ①它使主存与CPU的固定联系脱钩,主存既可被CPU访问,又可被外存访问。

    ②在数据块传送时,主存地址的确定、传送数据的计数等由硬件电路直接实现。

    ③主存中要开辟专用缓冲区,及时供给和接受外设的数据。

    ④DMA传送数据块,CPU和外设并行工作,提高了系统效率。

    ⑤DMA在传送开始前要通过程序进行预处理,结束后要通过中断方式进行后处理。

    2.DMA控制器的组成

    对数据传送过程中进行控制的硬件称为DMA控制器(DMA接口)。当I/O设备需要进行数据传送时,通过DMA控制器向CPU提出DMA传送请求,CPU响应之后让出系统总线,由DMA控制器接管总线进行数据传送。

    1)接受外设发出的DMA请求,并向CPU发出总线请求。

    2)CPU响应总线请求,发出总线响应信号,接管总线控制权,进入DMA操作周期。

    3)确定传送数据的主存单元地址及长度,并能自动修改主存地址计数和传送长度计数。

    4)规定数据在主存和外设间的传送方向,发出读写等控制信号,执行数据传送操作。

    5)向CPU发送DMA操作的结束。

    主存地址计数器:存放要交换数据的主存地址。

    传送长度计数器:用来记录传送数据的长度。计数溢出时,数据即传送完毕,自动发出中断请求信号。

    数据缓冲寄存器:用于暂存每次传送的数据。

    DMA请求触发器:每当I/O设备准备好数据后给出一个控制信号,使DMA请求触发器置位。

    “控制/状态”逻辑:由控制和时序电路及状态标志组成,用于指定传动方向,修改传送参数,并对DMA请求信号和CPU响应信号进行协调和同步。

    中断机构:当一个数据块传送完毕后触发中断机构,向CPU提出中断请求。

    在DMA传送过程中,DMA控制器将接管CPU的地址总线、数据总线和控制总线,CPU的主存控制信号被禁止使用。而当DMA传送结束后,将恢复CPU的一切权利并开始执行其操作。由此可见,DMA控制器必须具有控制系统总线的能力

    3.DMA的传送方式

    主存和DMA控制器之间有一条数据通路,因此主存和I/O设备之间交换信息时。不通过CPU。但当I/O设备和CPU同时访问主存时,可能发生冲突,为了有效地使用主存,DMA控制器与CPU通常外用以下三种方式使用主存:
    (1)停止CPU访问主存

    这种方式是当外设需要传送组数据时,由DMA接口向CPU发送一个信号,要求CPU放弃地址线、数据线和有关控制线的使用权,DMA接口获得总线控制权后,开始进行数据传送,在数据传送结束后,DMA接口通知CPU可以使用主存,并把总线控制权交还给CPU。这种传送过程中,CPU基本处于不工作状态和保持原状态。

    (2)DMA与CPU交替访存

    这种方式适用于CPU的工作周期比主存存取周期长的情况。例如,CPU的工作周期是1.2us,主存的存取周期小于0.6us,那么可将一个CPU周期分为C1和C2两个周期。其中C1专供DMA访存,C2专供CPU访存。这种方式不需要总线使用权的申请、建立和归还过程,总线使用权是通过C1和C2分时控制的。

    (3)周期挪用

    这种方式是前两种方式的折中,当I/O设备没有DMA请求时,CPU按程序的要求访问主存,一旦I/O设备有了DMA请求,会遇到3种情况。第一种是此时CPU不在访存(如CPU正在执行乘法指令),故I/O的访存请求与CPU未发生冲突;第2种是CPU正在访存,则必须等待存取周期结束后,CPU再将总线占有权让出。第3种是I/O和CPU同时请求访存,出现了访存冲突,此时CPU要暂时放弃总线占用权,由I/O设备挪用一个或几个存取周期。

    4.DMA的传送过程

    DMA的数据传送分为预处理、数据传送和后处理3个阶段。

    (1)预处理

    由CPU完成一些必要的准备工作。首先,CPU执行几条I/O指令,用以测试I/O设备状态,向DMA控制器的有关寄存器置初值,设置传送方向、启动该设备等。然后,CPU继续执行原来的程序,直到I/O设备准备好发送的数据(输入情况)或接受的数据(输出情况)时,I/O设备向DMA控制器发送DMA请求,再由DMA控制器向CPU发送总线请求(有时将这两个过程统称为DMA请求),用以传输数据。

    (2)数据传送

    DMA的数据传输可以以单字节(或字)为基本单位,对于以数据块为单位的传送(如硬盘),DMA占用总线后的数据输入和输出操作都是通过循环来实现的。需要指出的是,这一循环也是由DMA控制器(而不是通过CPU执行程序)实现的,也就是说,数据传送阶段是完全由DMA(硬件)来控制的。

    (3)后处理

    DMA控制器向CPU发送中断请求,CPU执行中断服务程序做DMA结束处理,包括检验送入主存的数据是否正确,测试传送过程中是否出错(错误则转入诊断程序)和决定是否继续使用DMA传送其他数据块等。

    5.DMA方式和中断方式的区别

    DMA方式和中断方式的重要区别:
    ①中断方式是程序的切换,需要保护和恢复现场,而DMA方式除了预处理和后处理,其他时候不占用CPU的任何资源。

    ②对中断请求的响应只能发生在每条指令执行完毕时(即指令的执行周期之后),而对DMA请求的响应可以发生在每个机器周期的结束时(在取值周期,间址周期,执行周期之后均可),只要CPU不占用总线就可以被响应。

    ③中断传输过程需要CPU的干预;而DMA传输过程不需要CPU的干预,故数据传输速率非常高,适合高速外设的成组数据传送。

    ④DMA请求的优先级高于中断请求。

    ⑤中断方式具有对异常事件的处理能力,而DMA方式仅局限于传输数据块的I/O操作。

    ⑥从数据传送来看,中断方式靠程序传送,DMA方式靠硬件传送。

    展开全文
  • dma

    千次阅读 2014-01-03 18:35:25
    DMA本来不属于CPU体系架构部分的内容,只因为在开发中经常要用到其相关的知识,所以这里就其基本概念、工作原理、常见问题做一个总结。 DMA概述 DMA的英文拼写是“Direct Memory Access”,汉语的意思就是直接...

    DMA本来不属于CPU体系架构部分的内容,只因为在开发中经常要用到其相关的知识,所以这里就其基本概念、工作原理、常见问题做一个总结。

    DMA概述

    DMA的英文拼写是“Direct Memory Access”,汉语的意思就是直接内存访问。DMA既可以指内存和外设直接存取数据这种内存访问的计算机技术,又可以指实现该技术的硬件模块(对于通用计算机PC而言,DMA控制逻辑由CPU和DMA控制接口逻辑芯片共同组成,嵌入式系统的DMA控制器内建在处理器芯片内部,一般称为DMA控制器,DMAC)。

    DMA内存访问技术

    使用DMA的好处就是它不需要CPU的干预而直接服务外设,这样CPU就可以去处理别的事务,从而提高系统的效率,对于慢速设备,如UART,其作用只是降低CPU的使用率,但对于高速设备,如硬盘,它不只是降低CPU的使用率,而且能大大提高硬件设备的吞吐量。因为对于这种设备,CPU直接供应数据的速度太低。 因CPU只能一个总线周期最多存取一次总线,而且对于ARM,它不能把内存中A地址的值直接搬到B地址。它只能先把A地址的值搬到一个寄存器,然后再从这个寄存器搬到B地址。也就是说,对于ARM,要花费两个总线周期才能将A地址的值送到B地址。而DMA就不同了,一般系统中的DMA都有突发(Burst)传输的能力,在这种模式下,DMA能一次传输几个甚至几十个字节的数据,所以使用DMA能使设备的吞吐能力大为增强。

    使用DMA时我们必须要注意如下事实:

    • DMA使用物理地址,程序是使用虚拟地址的,所以配置DMA时必须将虚拟地址转化成物理地址。
    • 因为程序使用虚拟地址,而且一般使用cache地址,所以Cache中的内容与其物理地址(内存)的内容不一定一致,所以在启动DMA传输前一定要将该地址的cache刷新,即写入内存。
    • OS并不能保证每次分配到的内存空间在物理上是连续的。尤其是在系统使用过一段时间而又分配了一块比较大的内存时。所以每次都需要判断地址是不是连续的,如果不连续就需要把这段内存分成几段让DMA完成传输

    DMAC的基本配置

    DMA用于无需CPU的介入而直接由专用控制器(DMA控制器)建立源与目的传输的应用,因此,在大量数据传输中解放了CPU。PIC32微控制器中的DMA可用于映射到内存空间中的不同外设,如从存储区到SPI,UART或I2C等设备。DMA特性详见器件参考手册,这里仅对一些基本原理与功能做一个简析。

    地址寄存器存放DMA传输时存储单元地址
    字节计数器存放DMA传输的字节数
    控制寄存器存放由CPU设定的DMA传输方式,控制命令等
    状态寄存器存放DMAC当前的状态,包括有无DMA请求,是否结束等

    独立DMA控制芯片

    在课程《微机原理》中,会讲到X86下一片独立的DMA控制芯片8237A。8237A控制芯片各通道在PC机内的任务:

    • CH0:用作动态存储器的刷新控制
    • CH1:为用户预留
    • CH2:软盘驱动器数据传输用的DMA控制
    • CH3:硬盘驱动器数据传输用的DMA控制

    嵌入式设备中的DMA

    直接存储器存取(DMA)控制器是一种在系统内部转移数据的独特外设,可以将其视为一种能够通过一组专用总线将内部和外部存储器与每个具有DMA能力的外设连接起来的控制器。它之所以属于外设,是因为它是在处理器的编程控制下来执行传输的。值得注意的是,通常只有数据流量较大(kBps或者更高)的外设才需要支持DMA能力,这些应用方面典型的例子包括视频、音频和网络接口。

    一般而言,DMA控制器将包括一条地址总线、一条数据总线和控制寄存器。高效率的DMA控制器将具有访问其所需要的任意资源的能力,而无须处理器本身的介入,它必须能产生中断。最后,它必须能在控制器内部计算出地址。

    一个处理器可以包含多个DMA控制器。每个控制器有多个DMA通道,以及多条直接与存储器站(memory bank)和外设连接的总线,如图1所示。在很多高性能处理器中集成了两种类型的DMA控制器。第一类通常称为“系统DMA控制器”,可以实现对任何资源(外设和存储器)的访问,对于这种类型的控制器来说,信号周期数是以系统时钟(SCLK)来计数的,以ADI的Blackfin处理器为例,频率最高可达133MHz。第二类称为内部存储器DMA控制器(IMDMA),专门用于内部存储器所处位置之间的相互存取操作。因为存取都发生在内部(L1-L1、L1-L2,或者L2-L2),周期数的计数则以内核时钟(CCLK)为基准来进行,该时钟的速度可以超过600MHz。

    每个DMA控制器有一组FIFO,起到DMA子系统和外设或存储器之间的缓冲器的作用。对于MemDMA(Memory DMA)来说,传输的源端和目标端都有一组FIFO存在。当资源紧张而不能完成数据传输的话,则FIFO可以提供数据的暂存区,从而提高性能。

    因为通常会在代码初始化过程中对DMA控制器进行配置,内核就只需要在数据传输完成后对中断做出响应即可。你可以对DMA控制进行编程,让其与内核并行地移动数据,而同时让内核执行其基本的处理任务―那些应该让它专注完成的工作。

    在一个优化的应用中,内核永远不用参与任何数据的移动,而仅仅对L1存储器中的数据进行读写。于是,内核不需要等待数据的到来,因为DMA引擎会在内核准备读取数据之前将数据准备好。图2给出了处理器和DMA控制器间的交互关系。由处理器完成的操作步骤包括:建立传输,启用中断,生成中断时执行代码。返回到处理器的中断输入可以用来指示“数据已经准备好,可进行处理”。

    数据除了往来外设之外,还需要从一个存储器空间转移到另一个空间中。例如,视频源可以从一个 视频端口直接流入L3存储器,因为工作缓冲区规模太大,无法放入到存储器中。我们并不希望让处理器在每次需要执行计算时都从外部存储读取像素信息,因此为 了提高存取的效率,可以用一个存储器到存储器的DMA(MemDMA)来将像素转移到L1或者L2存储器中。

    到目前为之,我们还仅专注于数据的移动,但是DMA的传送能力并不总是用来移动数据。

    在最简单的MemDMA情况中,我们需要告诉DMA控制器源端地址、目标端地址和待传送的字的个数。每次传输的字的大小可以是8、16或者12位。 我们只需要改变数据传输每次的数据大小,就可以简单地增加DMA的灵活性。例如,采用非单一大小的传输方式时,我们以传输数据块的大小的倍数来作为地址增量。也就是说,若规定32位的传输和4个采样的跨度,则每次传输结束后,地址的增量为16字节(4个32位字)。

    DMA的设置

    目前有两类主要的DMA传输结构:寄存器模式和描述符模式。无论属于哪一类DMA,表1所描述的几类信息都会在DMA控制器中出现。当DMA以寄存器模式工作时,DMA控制器只是简单地利用寄存器中所存储的参数值。在描述符模式中,DMA控制器在存储器中查找自己的配置参数。

    基于寄存器的DMA

    在基于寄存器的DMA内部,处理器直接对DMA控制寄存器进行编程,来启动传输。基于寄存器的DMA提供了最佳的DMA控制器性能,因为寄存器并不需要不断地从存储器中的描述符上载入数据,而内核也不需要保持描述符。

    基于寄存器的DMA由两种子模式组成:自动缓冲(Autobuffer)模式和停止模式。在自动缓冲DMA中,当一个传输块传输完毕,控制寄存器就自动重新载入其最初的设定值,同一个DMA进程重新启动,开销为零。

    正如我们在图3中所看到的那样,如果将一个自动缓冲DMA设定为从外设传输一定数量的字到 L1数据存储器的缓冲器上,则DMA控制器将会在最后一个字传输完成的时刻就迅速重新载入初始的参数。这构成了一个“循环缓冲器”,因为当一个量值被写入 到缓冲器的最后一个位置上时,下一个值将被写入到缓冲器的第一个位置上。

    自动缓冲DMA特别适合于对性能敏感的、存在持续数据流的应用。DMA控制器可以在独立于处理器其他活动的情况下读入数据流,然后在每次传输结束时,向内核发出中断。

    停止模式的工作方式与自动缓冲DMA类似,区别在于各寄存器在DMA结束后不会重新载入,因 此整个DMA传输只发生一次。停止模式对于基于某种事件的一次性传输来说十分有用。例如,非定期地将数据块从一个位置转移到另一个位置。当你需要对事件进 行同步时,这种模式也非常有用。例如,如果一个任务必须在下一次传输前完成的话,则停止模式可以确保各事件发生的先后顺序。此外,停止模式对于缓冲器的初 始化来说非常有用。

    描述符模型

    基于描述符(descriptor)的DMA要求在存储器中存入一组参数,以 启动DMA的系列操作。该描述符所包含的参数与那些通常通过编程写入DMA控制寄存器组的所有参数相同。不过,描述符还可以容许多个DMA操作序列串在一 起。在基于描述符的DMA操作中,我们可以对一个DMA通道进行编程,在当前的操作序列完成后,自动设置并启动另一次DMA传输。基于描述符的方式为管理 系统中的DMA传输提供了最大的灵活性。

    ADI 的Blackfin处理器上有两种主要的描述符方式―描述符阵列和描述符列表,这两种操作方式所要实现的目标是在灵活性和性能之间实现一种折中平衡。


    DMA控制器是一种在系统内部转移数据的独特外设,可以将其视为一种能够通过一组专用总线将内部和外部存储器与每个具有DMA能力的外设连接起来的控制器。它之所以属于外设,是因为它是在处理器的编程控制下来执行传输的。值得注意的是,通常只有数据流量较大(kBps或者更高)的外设才需要支持DMA能力,这些应用方面典型的例子包括视频、音频和网络接口。

        一般而言,DMA控制器将包括一条地址总线、一条数据总线和控制寄存器。高效率的DMA控制器将具有访问其所需要的任意资源的能力,而无须处理器本身的介入,它必须能产生中断。最后,它必须能在控制器内部计算出地址。

        一个处理器可以包含多个DMA控制器。每个控制器有多个DMA通道,以及多条直接与存储器站(memory bank)和外设连接的总线,如图1所示。在很多高性能处理器中集成了两种类型的DMA控制器。第一类通常称为“系统DMA控制器”,可以实现对任何资源(外设和存储器)的访问,对于这种类型的控制器来说,信号周期数是以系统时钟(SCLK)来计数的,以ADI的Blackfin处理器为例,频率最高可达133MHz。第二类称为内部存储器DMA控制器(IMDMA),专门用于内部存储器所处位置之间的相互存取操作。因为存取都发生在内部(L1-L1、L1-L2,或者L2-L2),周期数的计数则以内核时钟(CCLK)为基准来进行,该时钟的速度可以超过600MHz。

        每个DMA控制器有一组FIFO,起到DMA子系统和外设或存储器之间的缓冲器的作用。对于MemDMA(Memory DMA)来说,传输的源端和目标端都有一组FIFO存在。当资源紧张而不能完成数据传输的话,则FIFO可以提供数据的暂存区,从而提高性能。

        因为你通常会在代码初始化过程中对DMA控制器进行配置,内核就只需要在数据传输完成后对中断做出响应即可。你可以对DMA控制进行编程,让其与内核并行地移动数据,而同时让内核执行其基本的处理任务—那些应该让它专注完成的工作。

     

    图1:系统和存储器DMA架构.
    图1:系统和存储器DMA架构。

        在一个优化的应用中,内核永远不用参与任何数据的移动,而仅仅对L1存储器中的数据进行读写。于是,内核不需要等待数据的到来,因为DMA引擎会在内核准备读取数据之前将数据准备好。图2给出了处理器和DMA控制器间的交互关系。由处理器完成的操作步骤包括:建立传输,启用中断,生成中断时执行代码。返回到处理器的中断输入可以用来指示“数据已经准备好,可进行处理”。

     

    图2:DMA控制器.
    图2:DMA控制器。

        数据除了往来外设之外,还需要从一个存储器空间转移到另一个空间中。例如,视频源可以从一个视频端口直接流入L3存储器,因为工作缓冲区规模太大,无法放入到存储器中。我们并不希望让处理器在每次需要执行计算时都从外部存储读取像素信息,因此为了提高存取的效率,可以用一个存储器到存储器的DMA(MemDMA)来将像素转移到L1或者L2存储器中。

    到目前为之,我们还仅专注于数据的移动,但是DMA的传送能力并不总是用来移动数据。我们可以用代码覆盖的办法来提高性能,将DMA的控制器配置为在执行前把代码送入L1指令存储器。代码往往存储于较大的外部存储器中,而根据需要有选择性的送入L1。

    DMA控制器的编程

        让我们考察一下在定义DMA活动的过程中可以有哪些选项。我们将从最简单的模型开始,并在此基础上过渡到更为灵活的模型,这反过来增加了设置的复杂度。

        对于任何类型的DMA传输,我们都需要规定数据的起始源和目标地址。对于外设DMA的情况来说,外设的FIFO可以作为数据源或者目标端。当外设作为源端时,某个存储器的位置(内部或外部)则成为目标端地址。当外设作为目标端,存储的位置(内部或者外部)则成为源端地址。

    在最简单的MemDMA情况中,我们需要告诉DMA控制器源端地址、目标端地址和待传送的字的个数。采用外设DMA的情况下,我们规定数据的源端或者目标端,具体则取决于传输的方向。每次传输的字的大小可以是8、16或者12位。这种类型的事务代表了简单的1维(“1D”)统一“跨度”(unity stride)的传输。作为这一传输机制的一部分,DMA控制器连续跟踪不断增加的源端和目标端地址。采用这种传输方式时,8位的传输产生1字节的地址增量,而16位传输产生的增量为2字节,32位传输则产生4字节的增量。上面的参数是基本的1D DMA传输的设置参数。

        我们只需要改变数据传输每次的数据大小,就可以简单地增加一维DMA的灵活性。例如,采用非单一大小的传输方式时,我们以传输数据块的大小的倍数来作为地址增量。也就是说,若规定32位的传输和4个采样的跨度,则每次传输结束后,地址的增量为16字节(4个32位字)。

    虽然1D DMA得到了广泛的应用,但用处更大的则是2维(2D) DMA,特别是在视频应用中。2D功能是我们所讨论的1D DMA的情形的一种直接扩展。除了XCOUNT和XMODIFY值之外,我们还需对对应的YCOUNT和YMODIFY值进行编程设定。2D DMA可以简单地理解为一个嵌套的循环,即内循环由XCOUNT和XMODIFY来规定,外循环由YCOUNT和YMODIFY规定。一个1D DMA可以被简单的视为2D传输的“内循环”,如下形式:

    for y = 1 to YCOUNT

    for x = 1 to XCOUNT

    {

     

    }

    XMODIFY决定了XCOUNT每次减少时的DMA控制器的跨度值,而YMODIFY则决定了YCOUNT每次减少时对应的跨度值。与XCOUNT和XMODIFY一样,YOUNT可以以传输数量来定义,而YMODIFY则以字节数来定义。值得注意的是,YMODIFY可以为负值,这会让DMA控制器回转到缓冲器的起始点。

    对于外设DMA来说,传输的“存储器端”可以是1D或2D。不过,在外设端,传输始终是1D的。唯一的限制是在DMA每一端(源端和目标端)传输的字节总数必须相同。例如,如果我们从3个10字节的缓冲器向外设馈入数据。例如,如果我们从3个10字节的缓冲器向外设发送数据,外设必须被设定为传送30字节,具体方式则可以是任何可能的、所支持的传输宽度和传输计数值的组合。

        MemDMA提供的灵活度则要更高一些。例如,如果我们可以建立一个1D-2D传输、一个1D-2D传输、1个2D-1D传输,且可自然而然建立一个2D-2D传输,唯一的限制条件是,在DMA传输模块的两端所传送的字节总数必须相等。

    DMA的设置

        目前有两类主要的DMA传输结构:寄存器模式和描述符模式。无论属于哪一类DMA,表1所描述的几类信息都会在DMA控制器中出现。当DMA以寄存器模式工作时,DMA控制器只是简单地利用寄存器中所存储的参数值。在描述符模式中,DMA控制器在存储器中查找自己的配置参数。

    表1:DMA寄存器
    表1:DMA寄存器

    基于寄存器的DMA

        在基于寄存器的DMA内部,处理器直接对DMA控制寄存器进行编程,来启动传输。基于寄存器的DMA提供了最佳的DMA控制器性能,因为寄存器并不需要不断地从存储器中的描述符上载入数据,而内核也不需要保持描述符。

        基于寄存器的DMA由两种子模式组成:自动缓冲(Autobuffer)模式和停止模式。在自动缓冲DMA中,当一个传输块传输完毕,控制寄存器就自动重新载入其最初的设定值,同一个DMA进程重新启动,开销为零。

        正如我们在图3中所看到的那样,如果将一个自动缓冲DMA设定为从外设传输一定数量的字到L1数据存储器的缓冲器上,则DMA控制器将会在最后一个字传输完成的时刻就迅速重新载入初始的参数。这构成了一个“循环缓冲器”,因为当一个量值被写入到缓冲器的最后一个位置上时,下一个值将被写入到缓冲器的第一个位置上。

     

    图3:用DMA实现循环缓冲器.
    图3:用DMA实现循环缓冲器。

    自动缓冲DMA特别适合于对性能敏感的、存在持续数据流的应用。DMA控制器可以在独立于处理器其他活动的情况下读入数据流,然后在每次传输结束时,向内核发出中断。虽然有可能以恰当的方式阻止自动缓冲模式,但如果DMA进程需要定期启动和停止时,采用这种工作方式就没有什么意义。

    停止模式的工作方式与自动缓冲DMA类似,区别在于各寄存器在DMA结束后不会重新载入,因此整个DMA传输只发生一次。停止模式对于基于某种事件的一次性传输来说十分有用。例如,非定期地将数据块从一个位置转移到另一个位置。当你需要对事件进行同步时,这种模式也非常有用。例如,如果一个任务必须在下一次传输前完成的话,则停止模式可以确保各事件发生的先后顺序。此外,停止模式对于缓冲器的初始化来说非常有用。

    描述符模型

        基于描述符(descriptor)的DMA要求在存储器中存入一组参数,以启动DMA的系列操作。该描述符所包含的参数与那些通常通过编程写入DMA控制寄存器组的所有参数相同。不过,描述符还可以容许多个DMA操作序列串在一起。在基于描述符的DMA操作中,我们可以对一个DMA通道进行编程,在当前的操作序列完成后,自动设置并启动另一次DMA传输。基于描述符的方式为管理系统中的DMA传输提供了最大的灵活性。

    ADI 的Blackfin处理器上有两种主要的描述符方式—描述符阵列和描述符列表,这两种操作方式所要实现的目标是在灵活性和性能之间实现一种折中平衡。

        在描述符阵列模式下,描述符驻留在连续的存储器位置上。DMA控制器依然从存储器取用描述符,但是因为下一个描述符紧跟着当前的描述符,说明到何处去寻找下一个描述符(以及它们相应的描述符取用)的两个数据字就并不必要。因为描述符并不包含这一“下一描述符”指针项,DMA控制器希望一组描述符在存储器相互挨在一起,如同阵列一般。

        当各描述符在存储器中的分布位置并非“背对背”时,可以使用一个描述符列表。实际上这里涉及多种子模式,从而再一次实现了性能和灵活性之间的折中平衡。在“小描述符”模型中,描述符包括了一个单16位的域,用来给出“下一描述符指针”域的低位部分;高位部分则通过寄存器来独立编程设定,并且不发生改变。当然,这将描述符限制在存储器中一个特定的64K(=216)页面上。当描述符的位置需要跨越这一边界时,也可以提供一个“大”模型,它可以为“下一描述符指针”项提供32位的位置。

    无论采用何种描述符模式,描述符的量值数越多,则描述符取用的次数就越多。这也就是为何Blackfin处理器定义了一个“柔性描述符方式”的原因,该模式可以修改描述符的长度,使之仅仅包括特定传输所需要的数据。例如,如果不需要2D DMA,YMODIFY和 YCOUNT 寄存器就不需要成为描述符数据块的一部分。

    描述符管理

        管理描述符列表的最佳方法是什么?其实,这个问题的答案需要根据应用来定,但要明白存在何种替代方法很重要。

        我们将描述的第一种选择,其工作方式非常类似于一个自动缓冲DMA。它需要设定多种描述符,并将其串连到一起,正如图4a所示的那样。“串连”一词意味着一个描述符指向下一个描述符,描述符的载入是自动的。为了使链条完整,最后一个描述符反向指向第一个描述符,于是整个流程就重复下去。使用这种技术而不是自动缓冲的一个理由就是,这些描述符可以保证传输的规模和方向上具有更大的灵活性。

     

    图4:由处理器进行调控的DMA描述符:(a)链接的描述符列表;(b)
    图4:由处理器进行调控的DMA描述符:(a)链接的描述符列表;(b)“节流调节式”的描述符管理。

        第二个选择则是由处理器来管理描述符列表。回想一下,描述符实际上是存储器中的一个结构,每个描述符包含了一个配置字。每个配置字包含了“使能”位,其作用是在传输开始时进行调节。如果我们需要让处理器在做好准备时去启动每次具体的传输,我们就可以事先设定好所有的描述符,但把“使能”位清零。当处理器确定启动描述符的时机已经到来时,它只需简单地更新存储器中的描述符,然后写入DMA寄存器中,以让处于停止状态的通道启动起来。图4b示出了这一流程的一个例子。

        这种类型的传输什么时候有用呢?请考虑一个需要将输入流与输出流实现同步的多媒体应用。例如,我们接收视频采样,将其传输到存储器的速率可能会不同于将该视频输出显示的速度。在实际系统中,即使你试图让流以恰好相同的时钟传输,也会发生这种情况。在同步成问题的情况下,处理器可以调整对应于输出缓冲器的DMA描述符。在下一个描述符启用时,处理器可以通过调整目前的输出描述符来实现流的同步,具体方式是利用一种信号量机制(semaphore mechanism)来确保每次只有一个项访问共享资源。

        在处理器之间使用内部的DMA描述符链或者基于DMA的流时,一种有用的做法是在所传输的数据块的末尾添加一个额外的字,用以帮助标识正被发送的包,包括关于应该如何处理数据的信息和时间戳。图4b中虚线所划出的区域则示出了这种方案。

        大多数成熟的应用都有以软件形式实现的“DMA 管理器”功能。这可以作为操作系统或者实时内核的一部分来提供,但它也可以在没有这两者的条件下运行。在Blackfin处理器上,该功能可以作为VisualDSP++工具包的‘System Services’的一部分提供。这一管理功能可以让你通过标准的API来转移数据,而不必手工去配置每一个控制寄存器。

        基本上,一个应用将DMA描述符的要求提交给DMA队列管理器,其责任是处理每一次请求。请求的处理则是按照它们被应用软件接收到的顺序来进行的。指向“回调”函数的地址指针往往也是系统的一部分。该函数可以完成在数据缓冲准备好时你希望处理器来完成的工作,无需让内核停留在高优先级的中断服务例程的执行中。总的来说,DMA管理器可以简化编程模型,因为它对数据的传输进行了抽象。

        管理采用中断的描述符队列可以有两种通用的方法:第一种基于在每次描述符完结时所发出的中断,只有当你能确保每个中断事件将单独得到服务、无中断溢出时,才使用这种方法;第二种方法是仅仅在由一个工作块的最后一个描述符所规定的工作传输结束时发出中断。工作块是一个或者多个描述符的集合。

        为了保持描述符队列的同步,非中断型软件就必须维持一个添加到队列中的描述符数量的计数,而中断处理程序则维持一个对已完结的、从队列中除去的描述符的计数。计数次数仅仅在DMA完成对所有的描述符的处理后暂停时才会相等。

    本文小结

        本文中,我们讨论了DMA数据流的结构:基于寄存器的和基于描述符的,以及何时使用其中的某种结构。在下一期中,我们将分析某些先进的DMA功能特色,这些功能将协助数据在多媒体系统中有效地移动。


    展开全文
  • DMA

    千次阅读 2011-11-21 15:13:33
    DMA原理:DMA 是所有现代电脑的重要特色,他允许不同速度的硬件装置来沟通,而不需要依于 CPU 的大量 中断 负载。否则,CPU 需要从 来源 把每一片段的资料复制到 暂存器,然后把他们再次写回到新的地方。在这个时间...
      
    

    DMA - 街角的祝福 -  demoDMA - 街角的祝福 -  demo

     

    DMA原理:DMA 是所有现代电脑的重要特色,他允许不同速度的硬件装置来沟通,而不需要依于 CPU 的大量 中断 负载。否则,CPU 需要从 来源 把每一片段的资料复制到 暂存器,然后把他们再次写回到新的地方。在这个时间中,CPU 对于其他的工作来说就无法使用。 DMA 传输重要地将一个内存区从一个装置复制到另外一个。当 CPU 初始化这个传输动作,传输动作本身是由 DMA 控制器 来实行和完成。典型的例子就是移动一个外部内存的区块到芯片内部更快的内存去。像是这样的操作并没有让处理器工作拖延,反而可以被重新排程去处理其他的工作。DMA 传输对于高效能 嵌入式系统 算法和网络是很重要的。 
      在实现DMA传输时,是由DMA控制器直接掌管总线,因此,存在着一个总线控制权转移问题。即DMA传输前,CPU要把总线控制权交给DMA控制器,而在结束DMA传输后,DMA控制器应立即把总线控制权再交回给CPU。
    DMA - 街角的祝福 -  demo
    DMA
    一个完整的DMA传输过程必须经过下面的4个步骤。
    1.DMA请求
      CPU对DMA控制器初始化,并向I/O接口发出操作命令,I/O接口提出DMA请求。
    2.DMA响应
      DMA控制器对DMA请求判别优先级及屏蔽,向总线裁决逻辑提出总线请求。当CPU执行完当前总线周期即可释放总线控制权。此时,总线裁决逻辑输出总线应答,表示DMA已经响应,通过DMA控制器通知I/O接口开始DMA传输。
    3.DMA传输
      DMA控制器获得总线控制权后,CPU即刻挂起或只执行内部操作,由DMA控制器输出读写命令,直接控制RAM与I/O接口进行DMA传输。
    4.DMA结束
      当完成规定的成批数据传送后,DMA控制器即释放总线控制权,并向I/O接口发出结束信号。当I/O接口收到结束信号后,一方面停 止I/O设备的工作,另一方面向CPU提出中断请求,使CPU从不介入的状态解脱,并执行一段检查本次DMA传输操作正确性的代码。最后,带着本次操作结果及状态继续执行原来的程序。
      由此可见,DMA传输方式无需CPU直接控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为RAM与I/O设备开辟一条直接传送数据的通路,使CPU的效率大为提高。

    DMA操作模式
        DMA用于无需CPU的介入而直接由专用控制器建立源与目的传输的应用,因此,在大量数据传输中解放了CPU。PIC32微控制器中的DMA可用于映射到内存空间中的不同外设,从存储区到SPI,UART或I2C等设备。DMA特性详见器件参考手册,这里仅对一些基本原理与功能做一个简析。
        PIC32中DMA的传输涉及到几个基本的术语
        Event:事件,触发控制器启动或停止DMA传输的操作;
        Transaction:事务,单字传输(最多可以到4个字节),由读/写组成;
        Cell transfer:元传输,单次共DCHXCSIZE个字节的数据传输。元传输由单个或多个事务组成。
        Block transfer:块传输,块传输总的字节数由DCHXSSIZ或DCHXDSIZ决定。块传输由单个或多个元传输组成。
        事件是触发DMA控制器产生动作的方式,分为,START EVENT->启动传输;ABORT EVENT->取消传输;STOP EVENT->停止传输;为了有一个完整的概念认识,可以把用户软件的操作,如置位启动传输位等也包含在事件范围内。由此,可以看出,任何一个DMA动作都是由事件触发完成的。用户在使用DMA控制器时只需设计好事件与DMA操作的关联即可。要充分的使用DMA控制器,熟悉DMA各种工作模式的原理是很有必要的。
             传输模式二:字符匹配终止模式
        字符匹配模式用于传输不定长字节,而又有传输终止标识字节的应用环境中,Uart是这种模式的应用案例

         DMA通道的自动使能模式
        DMA每个通道在正常的块传输、终结字符匹配后或者因异常ABORT后,通道自动禁能。如果该通道有多次的块传输,需要手动的使能通道;为了省却该操作,DCHXCON寄存器提供了允许自动使能通道的位CHAEN(channel auto enable)。通道使能位CHEN在取消传输或ABORT事件发生时会被置为0。
    注:
    1、通道起始/终止/停止中断事件独立于中断控制器,因此相应的中断无需使能,也无需在DMA传输后清除相应的位;
    2、通道优先级和选择
        DMA控制器每个通道有一个自然的优先级,CH0默认为最高,CH4默认为最低;通道寄存器DCHXCON中提供了修改优先级的控制位。优先级控制了通道的传输顺序。
     
    3、DMA传输中的字节对齐
        PIC32采用的数据总线是32位,4字节;无疑访问地址为4字节对齐的访问效率最高,但是,如果把所有的常量或变量存储地址都限制在4字节对齐显然是不可能的;DMA中在处理这个问题上采用的字节对齐方法(存储方式为LSB)。举例来说,如果当前物理地址与4的模为0,则取4字节;模为1,则取高3字节;模为2,则取高2字节;模为3,则取高1字节。
        物理地址为0x1230,模为0,则取从0x1230处4字节数据;
        物理地址为0x1231,模为1,则取从0x1231处3字节数据;
        物理地址为0x1232,模为2,则取从0x1232处2字节数据;
        物理地址为0x1233,模为3,则取从0x1233处1字节数据;
        读/写过程均采取相同的字节对齐机制。DMA传输中的字节对齐过程如图2.

         直接存储器存取(DMA)控制器是一种在系统内部转移数据的独特外设,可以将其视为一种能够通过一组专用总线将内部和外部存储器与每个具有DMA能力的外设连接起来的控制器。它之所以属于外设,是因为它是在处理器的编程控制下来执行传输的。值得注意的是,通常只有数据流量较大(kBps或者更高)的外设才需要支持DMA能力,这些应用方面典型的例子包括视频、音频和网络接口

    一般而言,DMA控制器将包括一条地址总线、一条数据总线和控制寄存器。高效率的DMA控制器将具有访问其所需要的任意资源的能力,而无须处理器本身的介入,它必须能产生中断。最后,它必须能在控制器内部计算出地址。

    一个处理器可以包含多个DMA控制器。每个控制器有多个DMA通道,以及多条直接与存储器站(memory bank)和外设连接的总线如图1所示。在很多高性能处理器中集成了两种类型的DMA控制器。第一类通常称为“系统DMA控制器”,可以实现对任何资源(外设和存储器)的访问,对于这种类型的控制器来说,信号周期数是以系统时钟(SCLK)来计数的,以ADI的Blackfin处理器为例,频率最高可达133MHz。第二类称为内部存储器DMA控制器(IMDMA),专门用于内部存储器所处位置之间的相互存取操作。因为存取都发生在内部(L1-L1、L1-L2,或者L2-L2),周期数的计数则以内核时钟(CCLK)为基准来进行,该时钟的速度可以超过600MHz

    每个DMA控制器有一组FIFO,起到DMA子系统和外设或存储器之间的缓冲器的作用。对于MemDMA(Memory DMA)来说,传输的源端和目标端都有一组FIFO存在。当资源紧张而不能完成数据传输的话,则FIFO可以提供数据的暂存区,从而提高性能。

    因为通常会在代码初始化过程中对DMA控制器进行配置,内核就只需要在数据传输完成后对中断做出响应即可。你可以对DMA控制进行编程,让其与内核并行地移动数据,而同时让内核执行其基本的处理任务—那些应该让它专注完成的工作。

    图1:系统和存储器DMA架构.
    图1:系统和存储器DMA架构。

    在一个优化的应用中,内核永远不用参与任何数据的移动,而仅仅对L1存储器中的数据进行读写。于是,内核不需要等待数据的到来,因为DMA引擎会在内核准备读取数据之前将数据准备好。图2给出了处理器和DMA控制器间的交互关系。由处理器完成的操作步骤包括:建立传输,启用中断,生成中断时执行代码返回到处理器的中断输入可以用来指示“数据已经准备好,可进行处理”。

    图2:DMA控制器.
    图2:DMA控制器。

    数据除了往来外设之外,还需要从一个存储器空间转移到另一个空间中。例如,视频源可以从一个视频端口直接流入L3存储器,因为工作缓冲区规模太大,无法放入到存储器中。我们并不希望让处理器在每次需要执行计算时都从外部存储读取像素信息,因此为了提高存取的效率,可以用一个存储器到存储器的DMA(MemDMA)来将像素转移到L1或者L2存储器中。

    到目前为之,我们还仅专注于数据的移动,但是DMA的传送能力并不总是用来移动数据。  

     在最简单的MemDMA情况中,我们需要告诉DMA控制器源端地址、目标端地址和待传送的字的个数。每次传输的字的大小可以是8、16或者12位。  我们只需要改变数据传输每次的数据大小,就可以简单地增加DMA的灵活性。例如,采用非单一大小的传输方式时,我们以传输数据块的大小的倍数来作为地址增量。也就是说,若规定32位的传输和4个采样的跨度,则每次传输结束后,地址的增量为16字节(4个32位字)。

     

    DMA的设置

    目前有两类主要的DMA传输结构:寄存器模式和描述符模式。无论属于哪一类DMA,表1所描述的几类信息都会在DMA控制器中出现。当DMA以寄存器模式工作时,DMA控制器只是简单地利用寄存器中所存储的参数值。在描述符模式中,DMA控制器在存储器中查找自己的配置参数。

    表1:DMA寄存器
    表1:DMA寄存器

    基于寄存器的DMA

    在基于寄存器的DMA内部,处理器直接对DMA控制寄存器进行编程,来启动传输。基于寄存器的DMA提供了最佳的DMA控制器性能,因为寄存器并不需要不断地从存储器中的描述符上载入数据,而内核也不需要保持描述符。

    基于寄存器的DMA由两种子模式组成:自动缓冲(Autobuffer)模式和停止模式在自动缓冲DMA中,当一个传输块传输完毕,控制寄存器就自动重新载入其最初的设定值,同一个DMA进程重新启动,开销为零。

    正如我们在图3中所看到的那样,如果将一个自动缓冲DMA设定为从外设传输一定数量的字到L1数据存储器的缓冲器上,则DMA控制器将会在最后一个字传输完成的时刻就迅速重新载入初始的参数。这构成了一个“循环缓冲器”,因为当一个量值被写入到缓冲器的最后一个位置上时,下一个值将被写入到缓冲器的第一个位置上。

    图3:用DMA实现循环缓冲器.
    图3:用DMA实现循环缓冲器。

    自动缓冲DMA特别适合于对性能敏感的、存在持续数据流的应用。DMA控制器可以在独立于处理器其他活动的情况下读入数据流,然后在每次传输结束时,向内核发出中断。

    停止模式的工作方式与自动缓冲DMA类似,区别在于各寄存器在DMA结束后不会重新载入,因此整个DMA传输只发生一次。停止模式对于基于某种事件的一次性传输来说十分有用。例如,非定期地将数据块从一个位置转移到另一个位置。当你需要对事件进行同步时,这种模式也非常有用。例如,如果一个任务必须在下一次传输前完成的话,则停止模式可以确保各事件发生的先后顺序。此外,停止模式对于缓冲器的初始化来说非常有用。

    描述符模型

    基于描述符(descriptor)的DMA要求在存储器中存入一组参数,以启动DMA的系列操作。该描述符所包含的参数与那些通常通过编程写入DMA控制寄存器组的所有参数相同。不过,描述符还可以容许多个DMA操作序列串在一起。在基于描述符的DMA操作中,我们可以对一个DMA通道进行编程,在当前的操作序列完成后,自动设置并启动另一次DMA传输。基于描述符的方式为管理系统中的DMA传输提供了最大的灵活性。

    ADI 的Blackfin处理器上有两种主要的描述符方式—描述符阵列和描述符列表,这两种操作方式所要实现的目标是在灵活性和性能之间实现一种折中平衡。

     DMA 方式, 即外设在专用的接口电路DMA 控制器的控制下直接和存储器进行高速数据传送。采用DMA 方式时,如外设
    需要进行数据传输, 首先向DMA 控制器发出请求,DMA 再向CPU 发出总线请求,要求控制系统总线。CPU 响应DMA 控制器
    的总线请求并把总线控制权交给DMA, 然后在DMA 的控制下开始利用系统总线进行数据传输。数据传输结束后,DMA 并回
    总线控制权。
    DMA 操作步骤:
    (1) DMA 控制器的初始化
    (2) DMA 数据传送
    (3) DMA 结束
    DMA 初始化预置如下信息:一是指定I/O 设备对外设"读"还是"写",即指定其控制/状态寄存器中相应的控制位;二是数据应传送至何处,指定其地址的首地址;三是有多少数据字需要传送。


     

    展开全文
  • 【STM32】 DMA原理,步骤超细详解,一文看懂DMA

    万次阅读 多人点赞 2020-03-19 21:50:24
    DMA的基本介绍 什么是DMA (DMA的基本定义) DMA,全称Direct Memory Access,即直接存储器访问。 DMA传输将数据从一个地址空间复制到另一个地址空间,提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。 ...

    如需转载请注明地址:https://blog.csdn.net/as480133937/article/details/104927922


    DMA的基本介绍

    什么是DMA (DMA的基本定义)

    DMA,全称Direct Memory Access,即直接存储器访问。

    DMA传输将数据从一个地址空间复制到另一个地址空间,提供在外设和存储器之间或者存储器和存储器之间的高速数据传输

    我们知道CPU有转移数据、计算、控制程序转移等很多功能,系统运作的核心就是CPU

    CPU无时不刻的在处理着大量的事务,但有些事情却没有那么重要,比方说数据的复制和存储数据,如果我们把这部分的CPU资源拿出来,让CPU去处理其他的复杂计算事务,是不是能够更好的利用CPU的资源呢?

    因此:转移数据(尤其是转移大量数据)是可以不需要CPU参与。比如希望外设A的数据拷贝到外设B,只要给两种外设提供一条数据通路,直接让数据由A拷贝到B 不经过CPU的处理
    在这里插入图片描述
     DMA就是基于以上设想设计的,它的作用就是解决大量数据转移过度消耗CPU资源的问题。有了DMA使CPU更专注于更加实用的操作–计算、控制等。

    DMA定义:

    DMA用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU的干预,通过DMA数据可以快速地移动。这就节省了CPU的资源来做其他操作。

    DMA传输方式

    DMA的作用就是实现数据的直接传输,而去掉了传统数据传输需要CPU寄存器参与的环节,主要涉及四种情况的数据传输,但本质上是一样的,都是从内存的某一区域传输到内存的另一区域(外设的数据寄存器本质上就是内存的一个存储单元)。四种情况的数据传输如下:

    • 外设到内存
    • 内存到外设
    • 内存到内存
    • 外设到外设

    DMA传输参数

    我们知道,数据传输,首先需要的是1 数据的源地址 2 数据传输位置的目标地址 ,3 传递数据多少的数据传输量 ,4 进行多少次传输的传输模式 DMA所需要的核心参数,便是这四个

    当用户将参数设置好,主要涉及源地址、目标地址、传输数据量这三个,DMA控制器就会启动数据传输,当剩余传输数据量为0时 达到传输终点,结束DMA传输 ,当然,DMA 还有循环传输模式 当到达传输终点时会重新启动DMA传输。
      
    也就是说只要剩余传输数据量不是0,而且DMA是启动状态,那么就会发生数据传输。  
    在这里插入图片描述

    DMA的主要特征

    每个通道都直接连接专用的硬件DMA请求,每个通道都同样支持软件触发。这些功能通过软件来配置;

    • 在同一个DMA模块上,多个请求间的优先权可以通过软件编程设置(共有四级:很高、高、中等和低),优先权设置相等时由硬件决定(请求0优先于请求1,依此类推);
    • 独立数据源和目标数据区的传输宽度(字节、半字、全字),模拟打包和拆包的过程。源和目标地址必须按数据传输宽度对齐;
    • 支持循环的缓冲器管理;
    • 每个通道都有3个事件标志(DMA半传输、DMA传输完成和DMA传输出错),这3个事件标志逻辑或成为一个单独的中断请求;
    • 存储器和存储器间的传输、外设和存储器、存储器和外设之间的传输;
    • 闪存、SRAM、外设的SRAM、APB1、APB2和AHB外设均可作为访问的源和目标;
    • 可编程的数据传输数目:最大为65535。

    STM32少个DMA资源?

    对于大容量的STM32芯片有2个DMA控制器 两个DMA控制器,DMA1有7个通道,DMA2有5个通道。
    每个通道都可以配置一些外设的地址。

    ①DMA1 controller

    从外设(TIMx[x=1、2、3、4]、ADC1、SPI1、SPI/I2S2、I2Cx[x=1、2]和USARTx[x=1、2、3])产生的7个DMA请求,通过逻辑或输入到DMA1控制器 其中每个通道都对应着具体的外设:
    在这里插入图片描述
    在这里插入图片描述
    ② DMA2 controller

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

    这些在下方系统框图中也可以清晰地看到

    DMA工作系统框图

    在这里插入图片描述
    上方的框图,我们可以看到STM32内核,存储器,外设及DMA的连接,这些硬件最终通过各种各样的线连接到总线矩阵中,硬件结构之间的数据转移都经过总线矩阵的协调,使各个外设和谐的使用总线来传输数据。
    我们对他来进行一点一点的分析:

    下面看有与没有DMA的情况下,ADC采集的数据是怎样存放到SRAM中的?

    没有DMA

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

    内核通过DCode经过总线矩阵协调,从获取AHB存储的外设ADC采集的数据,

    然后内核再通过DCode经过总线矩阵协调把数据存放到内存SRAM中。

    在这里插入图片描述

    有DMA传输

    有DMA的话,

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

    在这里插入图片描述

    我们把上面的步骤专业一点介绍:

    在发生一个事件后,外设向DMA控制器发送一个请求信号。DMA控制器根据通道的优先权处理请求。当DMA控制器开始访问发出请求的外设时,DMA控制器立即发送给它一个应答信号。当从DMA控制器得到应答信号时,外设立即释放它的请求。一旦外设释放了这个请求,DMA控制器同时撤销应答信号。DMA传输结束,如果有更多的请求时,外设可以启动下一个周期。

    总之,每次DMA传送由3个操作组成:

    • 从外设数据寄存器或者从当前外设/存储器地址寄存器指示的存储器地址取数据,第一次传输时的开始地址是DMA_CPARx或DMA_CMARx寄存器指定的外设基地址或存储器单元;
    • 存数据到外设数据寄存器或者当前外设/存储器地址寄存器指示的存储器地址,第一次传输时的开始地址是DMA_CPARx或DMA_CMARx寄存器指定的外设基地址或存储器单元;
    • 执行一次DMA_CNDTRx寄存器的递减操作,该寄存器包含未完成的操作数目

    DMA传输方式

    方法1:DMA_Mode_Normal正常模式,

    当一次DMA数据传输完后,停止DMA传送 ,也就是只传输一次
      
    方法2:DMA_Mode_Circular循环传输模式

    当传输结束时,硬件自动会将传输数据量寄存器进行重装,进行下一轮的数据传输。 也就是多次传输模式

    仲裁器

    在这里插入图片描述
    仲裁器的作用是确定各个DMA传输的优先级

    仲裁器根据通道请求的优先级来启动外设/存储器的访问。

    优先权管理分2个阶段:

    软件:每个通道的优先权可以在DMA_CCRx寄存器中设置,有4个等级

    • 最高优先级
    • 高优先级
    • 中等优先级
    • 低优先级;

    硬件:如果2个请求有相同的软件优先级,则较低编号的通道比较高编号的通道有较高的优先权。比如:如果软件优先级相同,通道2优先于通道4。

    注意: 在大容量产品和互联型产品中,DMA1控制器拥有高于DMA2控制器的优先级。

    DMA数据流(仅存在于STM32F4 /M4 内核上)

    在设置了DMA的通道之后,还要选择通道对应外设的数据流

    8 个 DMA 控制器数据流都能够提供源和目标之间的单向传输链路。每个数据流配置后都可以执行:
    ● 常规类型事务:存储器到外设、外设到存储器或存储器到存储器的传输。
    ● 双缓冲区类型事务:使用存储器的两个存储器指针的双缓冲区传输(当 DMA 正在进行自/至缓冲区的读/写操作时,应用程序可以进行至/自其它缓冲区的写/读操作)。要传输的数据量(多达 65535)可以编程,并与连接到外设 AHB 端口的外设(请求 DMA 传输)的源宽度相关。每个事务完成后,包含要传输的数据项总量的寄存器都会递减。

    DMA_SxCR 寄存器控制数据流到底使用哪一个通道,每个数据流有 8 个通道可
    供选择,每次只能选择其中一个通道进行 DMA 传输。接下来,我们看看 DMA2 的各数据流通
    道映射表,如表 28.1.1 所示:
    在这里插入图片描述

    DMA 传输通道

    每个通道都可以在有固定地址的外设寄存器和存储器地址之间执行DMA传输。DMA传输的数据 量是可编程的,大达到65535。包含要传输的数据项数量的寄存器,在每次传输后递减。

    可编程的数据量:
    外设和存储器的传输数据量可以通过DMA_CCRx寄存器中的PSIZE和MSIZE位编程。

    指针递增模式

    根据 DMA_SxCR 寄存器中 PINC 和 MINC 位的状态,外设和存储器指针在每次传输后可以自动向后递增或保持常量。当设置为增量模式时,下一个要传输的地址将是前一个地址加上增量值

    通过单个寄存器访问外设源或目标数据时,禁止递增模式十分有用。

    如果使能了递增模式,则根据在 DMA_SxCR 寄存器 PSIZE 或 MSIZE 位中编程的数据宽度,下一次传输的地址将是前一次传输的地址递增 1个数据宽度、2个数据宽度或 4个数据宽度。

    存储器到存储器模式

    DMA通道的操作可以在没有外设请求的情况下进行,这种操作就是存储器到存储器模式。

    当设置了DMA_CCRx寄存器中的MEM2MEM位之后,在软件设置了DMA_CCRx寄存器中的EN位启动DMA通道时,DMA传输将马上开始。当DMA_CNDTRx寄存器变为0时,DMA传输结束。存储器到存储器模式不能与循环模式同时使用。

    这里要注意仅 DMA2 的外设接口可以访问存储器,所以仅 DMA2 控制器支持存储器到存储器的传输,DMA1 不支持。

    存储器到存储器模式不能与循环模式同时使用。

    DMA中断

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

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

    可编程的数据传输宽度、对齐方式和数据大小端
    当PSIZE和MSIZE不相同时,DMA模块按照下图进行数据对齐。

    注意:在大容量产品中, DMA2 通道 4 和 DMA2 通道 5 的中断被映射在同一个中断向量上。在互联型产品 中, DMA2 通道 4 和 DMA2 通道 5 的中断分别有独立的中断向量。所有其他的 DMA 通道都有自己的 中断向量

    DMA的内存占用

    在STM32控制器中,芯片采用Cortex-MX架构,总线结构有了很大的优化,DMA占用另外的地址总线,并不会与CPU的系统总线发生冲突。也就是说,DMA的使用不会影响CPU的运行速度

    但是要注意:
    DMA 控制器和Cortex-M3核共享系统数据总线执行直接存储器数据传输。当CPU和DMA同时访问相同的目标(RAM或外设)时,DMA请求可能会停止 CPU访问系统总线达若干个周期,总线仲裁器执行循环调度,以保证CPU至少可以得到一半的系统总线(存储器或外设)带宽。

    DMA配置部分

    此部分我们分为DMA寄存器和DMA库函数分别介绍:

    DMA寄存器

    DMA配置参数包括:通道地址、优先级、数据传输方向、存储器/外设数据宽度、存储器/外设地址是否增量、循环模式、数据传输量。

    DMA中断状态寄存器(DMA_ISR)

    在这里插入图片描述
    我们如果开启了 DMA_ISR 中这些中断,在达到条件后就会跳到中断服务函数里面去,即使 没开启,我们也可以通过查询这些位来获得当前 DMA 传输的状态。这里我们常用的是 TCIFx, 即通道 DMA 传输完成与否的标志。

    注意此寄存器为只读寄存器,所以在这些位被置位之后,只 能通过其他的操作来清除。

    DMA中断标志清除寄存器(DMA_IFCR)

    在这里插入图片描述
    DMA_IFCR 的各位就是用来清除 DMA_ISR 的对应位的,通过写 0 清除。在 DMA_ISR 被置位后, 我们必须通过向该位寄存器对应的位写入 0 来清除。

    DMA通道x配置寄存器(DMA_CCRx)

    在这里插入图片描述
    该寄存器控制着 DMA 的很多相关 信息,包括数据宽度、外设及存储器的宽度、通道优先级、增量模式、传输方向、中断允许、 使能等都是通过该寄存器来设置的。所以 DMA_CCRx 是 DMA 传输的核心控制寄存器

    DMA通道x传输数量寄存器(DMA_CNDTRx)(x = 1…7)

    在这里插入图片描述
    这个寄存器控制 DMA 通道 x 的每次 传输所要传输的数据量。其设置范围为 0~65535。并且该寄存器的值会随着传输的进行而减少, 当该寄存器的值为 0 的时候就代表此次数据传输已经全部发送完成了。所以可以通过这个寄存 器的值来知道当前 DMA 传输的进度

    DMA通道x外设地址寄存器(DMA_CPARx)(x = 1…7)

    在这里插入图片描述
    该寄存器用来存储 STM32 外设的地 址,比如我们使用串口 1,那么该寄存器必须写入 0x40013804(其实就是&USART1_DR)。如果使 用其他外设,就修改成相应外设的地址就行了。

    DMA通道x配置寄存器(DMA_CMARx)

    在这里插入图片描述
    ,该寄存器和 DMA_CPARx 差不多, 但是是用来放存储器的地址的。比如我们使用 SendBuf[5200]数组来做存储器,那么我们在 DMA_CMARx 中写入&SendBuff 就可以了。

    DMA寄存器配置流程

    通道配置过程 下面是配置DMA通道x的过程(x代表通道号):

    1. 在DMA_CPARx寄存器中设置外设寄存器的地址。发生外设数据传输请求时,这个地址将 是数据传输的源或目标。
    2. 在DMA_CMARx寄存器中设置数据存储器的地址。发生外设数据传输请求时,传输的数 据将从这个地址读出或写入这个地址。
    3. 在DMA_CNDTRx寄存器中设置要传输的数据量。在每个数据传输后,这个数值递减。
    4. 在DMA_CCRx寄存器的PL[1:0]位中设置通道的优先级。
    5. 在DMA_CCRx寄存器中设置数据传输的方向、循环模式、外设和存储器的增量模式、外 设和存储器的数据宽度、传输一半产生中断或传输完成产生中断。
    6. 设置DMA_CCRx寄存器的ENABLE位,启动该通道。

    一旦启动了DMA通道,它既可响应连到该通道上的外设的DMA请求。 当传输一半的数据后,半传输标志(HTIF)被置1,当设置了允许半传输中断位(HTIE)时,将产生 一个中断请求。在数据传输结束后,传输完成标志(TCIF)被置1,当设置了允许传输完成中断位 (TCIE)时,将产生一个中断请求。

    DMA库函数

    1.DMA初始化函数

     DMA_DeInit(DMAX_ChannelX);
    

    功能:将DMAyChannelx寄存器的初始化为其默认值

    注释:RCC_ResetCmd中对DMA无定义,因此采用的直接操纵DMA寄存器的方式

    
    void DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx,  DMA_InitTypeDef* DMA_InitStruct) 
    

    功能:设置要开启的通道,还有一些参数,包括外设基地址,存储器基地址,传输的数据量,增量模式,数据宽度等。

    具体看下方结构体代码介绍:

    typedef struct {  
     uint32_t DMA_PeripheralBaseAddr;   
     /*设置DMA源地址*/
     uint32_t DMA_MemoryBaseAddr;       
     /*设置DMA目的地址*/
     uint32_t DMA_DIR; 
     /* 设置数据传输方向,决定是从外设读取数据到内存还送从内存读取数 据发送到外设,也就是外设是源地还是目的地
     */                       
     uint32_t DMA_BufferSize;      
     /*设置传输大小*/    
     uint32_t DMA_PeripheralInc;       
     /*设置ReceiveBuff地址是否自增*/      
     uint32_t DMA_MemoryInc; 
     /*设置传输数据时候内存地址是否递,需要开启*/       
     uint32_t DMA_PeripheralDataSize;   
     /*外设的数据长度是为字节传输(8bits),半 字传输(16bits) 还是字传输(32bits) */    
     uint32_t DMA_MemoryDataSize;    
       /*设置内存的数据长度*/
     uint32_t DMA_Mode;      
     /*设置DMA的模式,正常模式/循环模式  是否循环发送*/        
     uint32_t DMA_Priority; 
      /*设置 DMA 通道的优先级,有低,中,高,超高四种模式*/        
     uint32_t DMA_M2M;    
      /*设置是否是存储器到存储器模式传输,*/       }
     DMA_InitTypeDef; 
    

    2.DMA使能函数

    void DMA_Cmd(DMA_Channel_TypeDef* DMAy_Channelx, FunctionalState  NewState);
    

    功能:使能或者失能DMA外设

    例如:DMA_Cmd(DMA1_Channel1 , ENABLE);
     3.DMA中断使能函数

    void DMA_ITConfig(DMA_Channel_TypeDef* DMAy_Channelx, uint32_t DMA_IT,  FunctionalState NewState);
    

    功能:配置指定的DMAy通道x的中断

    注释:DMA_IT_TC:传输完成 DMA_IT_HT:传输一半 DMA_IT_TE:传输错误

    例如:DMA_ITConfig(DMA1_Channel1 , DMA_IT_TC , ENABLE);

    4.设置CNDTRx和读CNDTRx函数 (通道传输数据量)

    void DMA_SetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx, uint16_t  DataNumber);
     uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx);
    

    作用:前者设置DMA通道的传输数据量(DMA处于关闭状态);后者获取当前DMA通道传输剩余数据量(DMA处于开启状态)。

    DMA库函数配置过程:

    • 使能DMA时钟:RCC_AHBPeriphClockCmd();
    • 初始化DMA通道:DMA_Init();
      • //设置通道;传输地址;传输方向;传输数据的数目;传输数据宽度;传输模式;优先级;是否开启存储器到存储器。
    • 使能外设DMA
      • 以串口为例:使能串口DMA发送,串口DMA使能函数。调用函数:USART_DMACmd();
    • 使能DMA通道传输;函数:DMA_Cmd();
    • 查询DMA传输状态。函数:DMA_GetFlagStatus();
    • 获取当前剩余数据量大小 函数: DMA_GetCurrDataCounter(DMA1_Channel4);

    UART DMA传输

    DMA就是一个搬运工,可以将数据从一个位置搬运到另一个位置。
    以UART为例,如果要接收数据,会触发UART中断,然后CPU介入,在中断中通过CPU将UART输入寄存器的值读出来,存放到内存中;
    而DMA方式,产生UART中断后,DMA直接参与,把UART输入寄存器的值搬运到内存中,CPU只需要在去检查内存的值就好了,这样提高了CPU的效率。

    DMA代码配置

    ① DMA初始化配置

    void dma_init()
    {
     
    DMA_InitTypeDef DMA_InitStructure;
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
    
    /*DMA配置*/
    
    DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_DR_Base;//串口数据寄存器地址
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SendBuff; //内存地址(要传输的变量的指针)
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //方向(从内存到外设)
    DMA_InitStructure.DMA_BufferSize = 500; //传输内容的大小
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址不增
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址自增
    DMA_InitStructure.DMA_PeripheralDataSize =
    DMA_PeripheralDataSize_Byte ; //外设数据单位
    DMA_InitStructure.DMA_MemoryDataSize =
    DMA_MemoryDataSize_Byte ; //内存数据单位
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ; //DMA模式:一次传输,循环
    DMA_InitStructure.DMA_Priority = DMA_Priority_Medium ; //优先级:高
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //禁止内存到内存的传输
     
    DMA_Init(DMA1_Channel4, &DMA_InitStructure); //配置DMA1的4通道
    DMA_Cmd(DMA1_Channel4,ENABLE);
    DMA_SetCurrDataCounter(DMA_CH4,DMA1_MEM_LEN);//DMA通道的DMA缓存的大小
    DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE);//配置DMA发送完成后产生中断
     
    }
    

    DMA中断

    void DMA1_Channel4_IRQHandler(void)
    {
    	if(DMA_GetFlagStatus(DMA1_FLAG_TC4)==SET)
    	{
    	
    		DMA_ClearFlag(DMA1_FLAG_TC4);
    	}
    }
    

    main函数

    #define SEND_BUF_SIZE 500	//发送数据长度,最好等于sizeof(TEXT_TO_SEND)+2的整数倍.
     
    u8 SendBuff[SEND_BUF_SIZE];	//发送数据缓冲区
    const u8 TEXT_TO_SEND[]={"STM32F1 DMA 串口实验"};
     uint16_t i;
    int main(void)
    {	   
    	uart_init(115200);	 	//串口初始化为115200
    		
    	for(i=0;i<500;i++)
    	{
    	SendBuff[i] =0xaf;
    	}	
    	USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);  //使能串口dma传输 
    	
    	while(1);
    =
    }
    

    在这里插入图片描述

    展开全文
  • 前言: 本系列教程将 对应外设原理,HAL库与STM32CubeMX结合在一起讲解,使您可以更快速的学会各个模块的使用 所用工具: 1、芯片: STM32F407ZET6/ STM32F103ZET6 ...DMA工作原理 STM32CubeMX创建...
  • ADCDMA_adc_adcDMA_dma_源码

    2021-09-30 07:29:24
    ADC+DMA实现了ADC从电位器读数据,再用DMA直接输出
  • stm32中关于DMA的应用,串口发送所占时间较长,用DMA来实现。
  • DMA控制器_dma_源码

    2021-10-04 11:12:11
    DMA 控制原理与结构图,基础知识对了解STM32和LPC17XX USB DMA有帮助
  • 实测可用的STM32F103的DMA实验
  • 配置dma驱动程序,适合stm32f10x系列的单片机驱动代码dma执行搬运操作
  • DMA_test_DMA数据传输.rar

    2021-04-02 23:08:20
    DMA_test_DMA数据传输
  • 基于STM32写的外设到外设的dma传输程序,方便移植,已测试完毕
  • 学习STM32的基础例程,对初学者很有帮助,主要是对DMA的基本操作
  • S3C2440开发板 DMA测试主程序
  • DMA之理解

    万次阅读 多人点赞 2018-09-12 12:32:37
    1、DMA由来 DMA(Direct Memory Access,直接存储器访问)。在DMA出现之前,CPU与外设之间的数据传送方式有程序传送方式、中断传送方式。CPU是通过系统总线与其他部件连接并进行数据传输。 1.1程序传送方式 程序...
  • DMA的verilog硬件实现,此版本为东南大学2005年版本。目测可用。 网上有很多该版本,但是不全,此次为收集齐全的版本方便大家学习研究。(没有找到文档说明,代码注释较详细)
  • DMA_APM32-DMA_源码

    2021-09-30 02:01:30
    APM32单片机DMA程序;替代STM32F030系列
  • DMA总结

    万次阅读 多人点赞 2015-06-25 12:16:23
    整个数据传输操作在一个称为"DMA控制器"的控制下进行的。CPU除了在数据传输开始和结束时做一点处理外(开始和结束时候要做中断处理),在传输过程中CPU可以进行其他的工作(前提是未设置停止CPU访问)。这样,在大...
  • RS232用的是串口1 对应的DMA通道是DMA2_Channel4
  • 在正点原子MINI开发板上测试的,串口DMA间隔2ms发送一次数据,串口空闲接收不定长数据。
  • 《STM32中文参考手册V10》-第10章 DMA控制器 DMA的基本介绍 DMA的基本定义 DMA,全称Direct Memory Access,即直接存储器访问。 DMA传输将数据从一个地址空间复制到另一个地址空间,提供在外设和存储器之间...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 104,069
精华内容 41,627
热门标签
关键字:

dma