在嵌入式系统中使用DMA——Part One

A guide to using Direct Memory Access in Embedded Systems – Part One 翻译笔记


本文介绍为什么使用DMA,以及使用DMA可以对系统整体性能带来的好处

DMA(Direct Memory Access)是计算机硬件的一个特性,它允许设备访问连接处理器和系统存储器的主总线,并在主存储器和系统的另一部分之间直接移动数据。
专用的DMA控制器通常集成在处理器中,它可以在主存储器和一系列子系统(包括存储器的另一部分)之间移动数据。
本文解释了在嵌入式系统中使用DMA的好处,在编写执行DMA传输的软件时需要考虑什么,以及一些需要注意的陷阱。

为什么使用DMA:

许多嵌入式系统都有产生或使用数据的内部和外部接口。例如,简单的UART、外部总线设备(如基于PCI的以太网控制器)或复杂的视频和图形设备。确保进出这些接口的数据得到正确处理,不丢失或损坏,是嵌入式系统的一个核心部分。

为了使系统可以对数据进行操作(解码消息,将数据发送到远程服务器等),数据通常必须在系统主存储器中,以便主处理器访问这些数据。在外围设备和主存储器之间移动数据的一种简单方法是,使用主处理器对要移动的每个字节或字执行加载或存储操作。处理器在传输每个字节或字之前必须等待外设准备就绪,这可以通过轮训设备的状态寄存器或处理来自设备的“就绪”中断来完成。这被称为编程I/O(Programmed I/O)

如果设备以低数据速率产生或消耗少量数据,programmed I/O 可能是管理主存数据内外传输的最佳方式;实际上,对于一些设备,例如简单的UART,这可能是唯一的方式。
然而,使用 programmed I/O 方式存在一些限制:首先,programmed I/O方式涉及软件循环,这可能会限制其性能。其次,对许多系统来说,这并不是一种使用处理器时间的好方式,因为处理器可能花费比必要或可用时间更多的时间在主存和外部接口之间移动数据。

另一种方式是建立DMA传输,它可以实现将数据移动到系统中的特定设备中。一旦处理器设置了DMA传输,它就可以在传输过程中执行其它操作,或者等待传输完成时的通知。这将释放处理器,使得处理器可以在传输过程中处理其它工作,提高系统性能。

一些外围设备有自己内置的DMA控制器,这意味着它们可以控制系统总线并执行DMA传输,而不需要单独的系统DMA控制器。能够控制系统总线的设备称为总线主机或具有总线控制能力的设备。典型的控制器有磁盘控制器、以太网控制器、USB控制器和视频控制器。通常,内置于这些设备中的DMA控制器只能在设备本身和主存之间移动数据,也就是说,它不能作用一般通用的系统DMA控制器。

其它使用DMA的理由:

使用DMA传输数据的明显好处是,CPU可以在数据传输过程中进行其它工作。然而,根据所设计的硬件,有时也能带来其它好处,例如:

  • 数据转换:特定于应用程序的处理器,例如一些针对视频或信号处理的处理器,可以使用使用DMA传输进行数据转换,包括字节序变换以及2D块传输。
  • 低功耗:如果处理器负载减少并且中断更少——例如,在整个传输完成时中断一次,而不是在传输完每项数据时中断一次,那么可以在DMA传输时以较低的时钟频率运行处理器,甚至进入低功耗模式。
  • 更高的数据吞吐量:给定的处理器可能能够以更高的数据率处理更多的外部接口数据,或者低端处理器可能能够处理更复杂的接口,如以太网或USB。
    DMA传输也通常用于多核处理器间的核间通信或多处理器间的处理器间通信。

DMA传输的类型:

为了评估使用DMA的好处和后果,有必要了解硬件级别上发生的事情。
根据硬件设计和所涉及的外围设备的不同,DMA传输可以采用不同的形式。最简单的称为单周期(single-cycle)DMA传输,通常用于在UARTs或音频编解码器等设备之间传输数据,这些设备每次产生或使用一个字的数据。在这种情况下,外围设备使用控制线发出信号,表示它有数据要传输或需要新的数据。当处理器或另一个总线主机没有使用总线时,授予DMA对总线的访问权,DMA控制器获得对系统总线的访问权,传输数据,然后释放总线。因此,单周期DMA传输与其它总线事务交织在一起,对处理器的操作影响不大。

另一种传输类型是突发传输(burst transfer)。传输从总线请求开始,当请求被允许时,数据以突发方式传输,例如一次128字节。突发大小取决于处理器体系结构和外围设备,并且可以根据硬件细节进行编程。
当突发传输事务发生时,处理器将无法访问系统总线,这可能会导致处理器因为无法获取新的运行指令或数据而停止运行,从而降低系统性能。为了最小化这个问题的影响,DMA控制器可以在固定数量的突发事务后或达到预先设定的带宽限制后释放总线。然后,系统总线仲裁逻辑决定下一个访问总线的总线主机,以及决定DMA传输何时将继续下一个块的传输。因此,如果系统需要执行大的DMA块传输,则系统设计者需要仔细计算所需的总线带宽要求,以确保硬件或软件设计中没有性能瓶颈。

执行DMA传输:

在DMA传输开始之前,处理器必须告诉DMA控制器或外围设备要移动多少数据,以及要将数据移动到哪或从哪里移动。对于专用的DMA控制器,这些通常涉及到编写一组描述传输的寄存器。具有DMA功能的外围设备也可能具有显式的DMA控制器寄存器。DMA传输通常具有这些属性:
源地址:数据源地址,位于主存或外设地址空间中。
目的地址:数据目的地址,位于主存或外设地址空间中。
传输长度:传输的总长度,以字节或字为单位。
传输类型:包括内存到外设,外设到内存,以及内存到内存,外设到外设。
块大小:执行突发传输时的块大小,在获得总线访问和再次请求之前要传输的数据量。

更复杂的DMA控制器可以执行二维传输,源和/或目的地址被视为由一些行列组成的二维内存块,而不是一个连续的块。对于这种类型的传输,还有两个更重要的属性:
行跨距(Line stride):2D缓冲区中每行的宽度。
行长度(Line length):从每行传输的字节数(<=line stride)。
二维传输的一个例子,是从视频帧中提取感兴趣的区域。行跨距就是整个图像的宽度,而行长度就是感兴趣区域的宽度。

一旦设置了传输的属性,就可以开始进行传输了。如果这个过程是在软件控制下完成的,处理器将写入DMA控制器中的控制寄存器来开始传输。如果传输依赖设备就绪,那么它可以由设备本身向控制器发送一个控制信号来启动。在传输结束时,设备或DMA控制器在处理器上产生一个中断,以表明有数据可供处理或需要建立一个新的传输。

当通过将所有传输属性编程到设备寄存器中来设置和启动传输时,它被称为直接DMA(direct DMA)传输。许多设备还支持链式DMA传输,这种模式下,传输属性是在特定于设备的数据结构中指定,通常称为DMA描述符,它类似于直接DMA寄存器集。链中每个描述符都有一个指向下一个描述符的指针。链中第一个描述符的地址通常被编程到设备的寄存器中。

每个描述符指向处理器中的单个内存块或数据缓冲区,它是传输的源或目标。内存如何对齐以及最大块大小可能有限制。例如,每个缓冲区可能必须对齐到32或64字节的地址边界,并限制为64K字节。
内存块通常不必是连续的,但每个缓冲区内的内存必须由连续的物理页组成。这种配置通常被称为分散-收集DMA,操作系统可能提供一些例程来帮助设备驱动程序构建和管理分散-收集内存缓冲区。当传输开始时,设备依次移动每个描述符指定的数据,直到到链的末端。根据硬件设计,可以在执行传输时在链的末端附加新的描述符,从而创建连续不间断的数据流。


参考连接
https://pebblebay.com/direct-memory-access-embedded-systems/