直接内存访问--DMA

DMA介绍、原理、工作模式 DMA,全称Direct Memory Access,直接存储器访问。DMA将数据从一个内存地址复制到另一个内存地址的操作,当然不仅仅局限于内存到内存,也可以外设和内存之间相互访问。那么DMA进行数据的搬移和普通通信方式(IIC、SPI)想比区别在哪,普通通信方式IIC或者SPI或多或少的到需要CPU的参与,CPU控制收发、读写,而DMA在进行数据传输的时候不需要CPU参与,因此大大降低了CPU的工作量。 阅读详情

DMA数据传输:

DMA允许外围设备和主内存之间直接传输 I/O 数据, DMA 依赖于系统。每一种体系结构DMA传输不同,编程接口也不同。

数据传输可以以两种方式触发:一种软件请求数据,另一种由硬件异步传输。

在第一种情况下,调用的步骤可以概括如下(以read为例):

(1)在进程调用 read 时,驱动程序的方法分配一个 DMA 缓冲区,随后指示硬件传送它的数据。进程进入睡眠。

(2)硬件将数据写入 DMA 缓冲区并在完成时产生一个中断。

(3)中断处理程序获得输入数据,应答中断,最后唤醒进程,该进程现在可以读取数据了。

第二种情形是在 DMA 被异步使用时发生的。以数据采集设备为例:

(1)硬件发出中断来通知新的数据已经到达。

(2)中断处理程序分配一个DMA缓冲区。

(3)外围设备将数据写入缓冲区,然后在完成时发出另一个中断。

(4)处理程序利用DMA分发新的数据,唤醒任何相关进程。

网卡传输也是如此,网卡有一个循环缓冲区(通常叫做 DMA 环形缓冲区)建立在与处理器共享的内存中。每一个输入数据包被放置在环形缓冲区中下一个可用缓冲区,并且发出中断。然后驱动程序将网络数据包传给内核的其它部分处理,并在环形缓冲区中放置一个新的 DMA 缓冲区。驱动程序在初始化时分配DMA缓冲区,并使用它们直到停止运行

分配DMA缓冲区:

1.使用DMA缓冲区的主要问题是:大于一页时,他们必须占据连续的物理页,因为设备使用ISA或者PCI系统总线传输数据,而这两种方式使用的都是物理地址。

2.实际操作中,一些设备和一些系统中的高端内存不能用于DMA,这是因为外围设备不能使用高端内存地址。应使用GFP_DMA标志调用kmalloc或者get_free_pages从DMA区间分配内存。

3.使用DMA的设备驱动程序将于连接到总线接口上的硬件通信,这些硬件通常使用的是总线地址。

unsigned long virt_to_bus(volatile void *address);

void *bus_to_virt(unsigned long address);

这些函数在虚拟地址和总线地址见做了简单的转化,但对于必须使用I/O内存管理单元或者必须使用回弹缓冲区的情况下,将不能工作。

通用DMA层:

内核提供了一个与总线--体系架构无关的DMA层,它会隐藏大多数问题,为DMA编写驱动时,使用该层。

使用些列函数的驱动程序都要包含头文件<linux/dma-mapping.h>

1.int  dma_set_mask (struct  device  *dev , u64  mask);用于判断给定寻址范围受限的设备在当前主机上是否具备DMA操作的能力。

   如果设备支持常见的32位DMA操作,则没有必要调用dma_set_mask。

2.DMA映射是分配一个DMA缓冲区和为该缓冲区生成设备可访问地址的操作的组合。

   DMA映射建立了一个新的结构类型--dma_addr_t来表示总线地址,dma_addr_t类型的变量对驱动是不透明的;如果cpu直接使用了该结构,将会导致发生不可   

    预期的问题。

    根据DMA缓冲区期望保留的时间长短,PCI代码区分两种类型的DMA映射

    一致性DMA映射:必须可以同时被cpu和外围设备访问。必须保存在一致性缓存中。

    流式DMA映射:通常为单独的操作建立流式映射,开发者建议尽量使用流式映射。

    2.1 内核中提供了一下函数用于分配一个DMA一致性的内存区域:

    void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp);

    这个函数的返回值为申请到的DMA缓冲区的虚拟地址。此外,该函数还通过参数handle返回DMA缓冲区的总线地址。与之对应的释放函数为:

    void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr_t handle);

    此外,Linux内核还提供了PCI设备申请DMA缓冲区的函数pci_alloc_consistent(),原型为:

    void *pci_alloc_consistent(struct pci_dev *dev, size_t size, dma_addr_t *dma_addrp);  对应的释放函数为:

    void pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu_addr, dma_addr_t dma_addr);

 

    2.2DMA池

    DMA池是一个生成小型、一致性DMA映射的机制。调用dma_alloc_coherent获得的映射,可能其最小大小为单个页。如果设备需要的DMA缓冲

    区比这还小,就要使用DMA池了。<linux/dmapool.h>

    struct dma_pool *dma_pool_create(const char *name,struct device *dev,size_t size,size_t align,size_t allocation);

    void *dma_pool_alloc(struct dma_pool *pool,int mem_flags,dma_addr_t *handle);

    void *dma_pool_free(struct dma_pool *pool,void *vaddr,dma_addr_t addr);

    void dma_pool_destroy(struct dma_pool *pool);

     2.3建立流式DMA映射

     2.3.1建立流式映射时,必须告诉内核数据流动的方向。dma_data_direction枚举类型:

     DMA_TO_DEVICE

     DMA_FROM_DEVICE

     DMA_BIDIRECTIONAL

     DMA_NONE

     2.3.2当只有一个缓冲区需要被传输时:

     dma_addr_t dma_map_single(struct device *dev,void *buffer,size_t size,enum dma_data_direction direction);

     返回值时总线地址,可以把返回值传递给设备。

     void dma_unmap_single(struct device *dev,dma_addr_t dma_addr,size_t size,enum dma_data_direction direction);

     size和direction参数必须与映射缓冲区的参数相匹配。

     2.3.3流式DMA映射的几条重要原则:

     传送方向匹配于映射时给定的方向值。

     一旦缓冲区被映射,它属于设备,而不是处理器,直到缓冲区被撤销映射前,驱动程序不能以任何方式访问其中的内容。

     在DMA处于活动期间内,不能撤销对缓冲区的映射

     因此,内核提供如下调用使驱动程序不需要撤销映射就访问流式DMA缓冲区的内容。

     void dma_sync_single_for_cpu(struct device *dev,dma_handle_t bus_addr,size_t size,enum dma_data_direction direction);

     void dma_sync_single_for_device(struct device *dev,dma_handle_t bus_addr,size_t size,enum dma_data_direction direction);

     2.4单页流式映射

     2.5分散/聚集映射

3.  ISA设备的DMA

     3.1

     ISA总线语序两种DMA传输:本地DMA和ISA总线控制DMA.这里主要说一下本地DMA

     有三种实体涉及到ISA总线上的DMA数据传输:

     DMA控制器:DMAC

     外围设备

     设备驱动程序

     在pc中,早期DMA控制器能够管理四个"通道",每个通道与一套DMA寄存器相关联.

     注册DMA:

     int request_dma(unsigned int channel,const char *name);        

     channel是0到7的整数,其中4不可用,通道4在内部用来将从属控制器级联到主控制器上。返回0表示成功。cascade入口是一个占位符,表示4通道不可用

     void free_dma(unsigned int channel);

     在open操作时请求通道比在模块初始化函数中请求通道更好一些。同时还建议在请求中断信号线以后请求DMA通道,在释放中断前释放DMA通道。

     3.2与DMA控制器通信

     DMA通道时一个可共享的资源,在配置通道的时候需要加锁。

     unsigned long claim_dma_lock()

     void release_dma_lock(unsigned lon;g flags);

     配置DMA通道的信息包含三部分:RAM地址,被传输的原子项个数(以字节为单位),传输的方向

     void set_dma_mode(unsigned int channel,char mode);

     void set_dma_addr(unsigned int channel,unsigned int addr);

     void set_dma_count(unsigned int channel,unsigned int count);

     除此之外,当处理DMA设备时,还有许多用于管理设备的函数:

     void disable_dma(unsigned int channel);

     void enable_dma(unsigned int channel);

     int get_dma_residue(unsigned int channel);     该函数返回还未传输的字节数,用于查看DMA传输是否已经结束。

     void clear_dma_ff                                                   

     程序员必须在访问DMA寄存器前清除触发器,触发器用于控制对16位寄存器的访问,我们可以通过两个连续的8位操作访问该寄存器

     当清零时被用来选择低字节,置位选择高字节。

    

 

DMA的解读 直接存储器访问(Direct Memory Access),简称DMA。前述的对I/O设备的数据搬运操作,无论是轮询方式还是中断方式,都需要CPU读写参与其中,在要进行大量数据传输时,CPU的利用效率将大大降低;DMA是CPU一个用于数据从一个地址空间到另一地址空间“搬运”(拷贝)的组件,数据拷贝过程不需CPU干预,数据拷贝结束则通知CPU处理。因此,大量数据拷贝时,使用DMA可以释放CPU资源。DMA就是基于以上设想设计的,它的作用就是解决大量数据转移过度消耗CPU资源的问题。 阅读详情

相关推荐

PCI设备的DMA映射操作详解

上周认真学习了LDD3第15章直接内存访问部分,这周调试PCI的网卡和视频采集卡,结合代码对DMA映射有了进一步的理解,这里按照LDD315章的顺序总结一下,记一下笔记,以后忘了再来翻,本人刚毕业1年菜鸟,理解不到的地方还希望大神指点!   根据LDD3说法,DMA是一种硬件机制,是说硬件具有这种仲裁能力,在cpu不干预的情况下设备可以作为主设备来对内存的直接读写访问,这样可以大大提高大数据流的

做一个有技术追求的人 1万+

DMA简介

为什么要有 DMA 技术? dma主要是用于读写数据用的 在没有 DMA 技术前,I/O 的过程是这样的: CPU 发出对应的指令给磁盘控制器,然后返回; 磁盘控制器收到指令后,于是就开始准备数据,会把数据放入到磁盘控制器的内部缓冲区中,然后产生一个中断; CPU 收到中断信号后,停下手头的工作,接着把磁盘控制器的缓冲区的数据一次一个字节地读进自己的寄存器,然后再把寄存器里的数据写入到内存,而在数据传输的期间 CPU 是无法执行其他任务的。 可以看到,整个数据的传输过程,都要需要 CPU 亲自.

羞羞滴小朋友 2万+

直接内存访问DMA)算法

DMA控制器根据预先设置好的传输参数(如源地址、目的地址、传输长度等),直接在内存和设备之间进行数据的搬移,期间不需要CPU频繁地参与每一个数据字节的传输操作。包括源地址寄存器(指定数据的来源地址,比如设备的数据缓冲区地址)、目的地址寄存器(指定数据要传输到的内存地址)、传输长度寄存器(指定要传输的数据字节数)等。请注意,以上代码只是为了演示DMA传输控制和缓冲区管理的基本原理和实现方式,在实际应用中,可能需要根据具体的硬件平台和系统环境进行更深入的调整和优化。• 首先将内存中的数据填充到DMA缓冲区。

qq_40844444的博客 1558

DMA外设详解

存储器到存储器,存储器到外设,外设到存储器以及串口空闲中断深入理解

k666499436的博客 3万+

【STM32】直接内存访问DMA

        直接内存访问DMA)允许不同速度的硬件装置来沟通,而不需要依赖于 CPU 的大量中断负载。在 STM32 中,DMA 可以在不占用 CPU 的情况下实现数据的快速传输,提高系统的效率。以下是一个基于 STM32Cube HAL 库的 DMA 驱动程序开发示例,以实现从内存到外设(如串口)的数据传输为例。

大雨淅淅的博客 1433

直接内存访问(DMA)

直接内存访问是一种硬件机制,它允许外围设备和主内存之间直接传输它们的I/O数据,而不需要系统处理器的参与。使用这种机制可以大大提高与设备通信的吞吐量。

缘起宇轩阁 7070

DMA访问(直接内存访问)

DMA的工作原理是,如果按数据块进行I/O,即需要传输大量数据时,就无须CPU的介入。在这种情况下,我们可以让I/O设备与计算机内存进行直接数据交换。而CPU则可以去忙别的事情。这种将CPU的介入减少的I/O模式称为直接内存访问。 问题是,将CPU从繁忙等待中解脱出来,难道DMA的整个数据读写过程不需要使用处理器的功能吗?当然不是。数据传输当然使用CPU,只不过这里使用的CPU不是计算机里面所有进程共享的CPU,而是由另外一个CPU来负责数据传输。这个另外的CPU就是DMA控制器。 也许读者会问,这有什么意

鸭梨的博客 1万+

CW32L052 DMA直接内存访问

CW32L052支持DMA(Direct Memory Access),即直接内存访问,无需CPU干预,实现高速数据传输。

weixin_70940338的博客 1190

直接内存访问——DMA

DMA是一种允许外设不经过CPU直接与内存交换数据的硬件机制,文章介绍了其工作原理、工作流程和应用场景。

wtmdnsn的博客 1616

直接内存访问 (Direct Memory Access, DMA)

Table of Contents 直接内存访问 (Direct Memory Access, DMA) DMA 模型 设备 DMA 的类型 总线主控器 DMA 第三方 DMA 第一方 DMA 主机平台 DMA 的类型 DMA 软件组件:句柄、窗口和 Cookie DMA 操作 执行总线主控器 DMA 传送 执行第一方 DMA 传送 执行第三方 DMA 传送 DMA 特性...

RToax 3042

DMA直接内存访问

DMA 直接内存访问DMA)是一种内存访问技术。它允许某些电脑内部的硬件子系统,可以独立地直接读写系统内存,而不需要中央处理器CPU介入处理。在同等程度的处理负担下,DMA是一种快速的数据传送方式。很多硬件的系统会使用DMA,包括硬件控制器,绘图显卡,网卡和声卡。 DMA是所有现代电脑的重要特色,它允许不同速度的硬件设备沟通,而不需要依赖于中央处理器的大量中断负载。否则,中央处理器需要从来源把每一片段的资料复制到寄存器,然后把它们再次写回到新的地方。在这个时候,中央处理器对于其他的工作来说就无法使用。 D

qq_36553387的博客 2732

集成电路学习:什么是DMA直接内存访问

DMA直接内存访问)是一种计算机数据传输技术,允许外设直接访问内存而不经过CPU。其工作流程包括CPU初始化、DMA请求、总线控制权转移、数据传输和结束信号五个步骤。DMA技术能显著降低CPU负担,提高数据传输速度,广泛应用于磁盘I/O、网络通信和图形处理等领域。这项技术是现代计算机系统中实现高效数据传输的关键手段。

limengshi138392的博客 1337

内存访问——直接内存访问(DMA)

1. 什么是DMA 直接内存访问是一种硬件机制,它允许外围设备和主内存之间直接传输它们的I/O数据,而不需要系统处理器的参与。使用这种机制可以大大提高与设备通信的吞吐量。 直接内存访问DMA)方式是一种完全由硬件执行I/O交换的工作方式。DMA控制器从CPU完全接管对总线的控制。数据交换不经过CPU,而直接在内存和I/O设备之间进行。 DMA控制器采用以下三种方式: ① 停止CPU访问内

守静默语 3388

linux中直接内存访问DMA

1. 什么是DMA 直接内存访问是一种硬件机制,它允许外围设备和主内存之间直接传输它们的I/O数据,而不需要系统处理器的参与。使用这种机制可以大大提高与设备通信的吞吐量。   2. DMA数据传输 有两种方式引发数据传输: 第一种情况:软件对数据的请求 1. 当进程调用read,驱动程序函数分配一个DMA缓冲区,并让硬件将数据传输到这个缓冲区中。进程处于睡眠状态。 2. 硬件将数据写

u014379540的博客 2453

直接内存访问(DMA) 总结

1. 什么是DMA 直接内存访问是一种硬件机制,它允许外围设备和主内存之间直接传输它们的I/O数据,而不需要系统处理器的参与。使用这种机制可以大大提高与设备通信的吞吐量。   2. DMA数据传输 有两种方式引发数据传输: 第一种情况:软件对数据的请求 1. 当进程调用read,驱动程序函数分配一个DMA缓冲区,并让硬件将数据传输到这个缓冲区中。进程处于睡眠状态。 2. 硬件将数据写

1733
上一篇: linux中直接 I/O 机制的介绍
下一篇: 内核定时器
xp_super
博客等级 码龄14年 10粉丝 17原创
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值