System DMA是将DMA作为中心位置挂在总线上,能够被总线上的任何设备所使用。BMD是目前为止发现的基于PCIe总线使用最多的DMA类型(使用Endpoint设备)。 MWr和MRd的TLPs会通过PIO(程控输入输出)被放松到endpoint端 并且被用来监视和控制DMA硬件.目标逻辑的功能是为了更新状态控制寄存器,所有即将到来的MWr数据包是32位宽并且包含一个双字的负载 初始化逻辑在从endpoint传输数据到系统存储中时产生内存写TLPs,DMA写控制和状态寄存器指定发送的地址、大小、负载内容以及TLPs的个数。
1.DMA方式的特点 主存和DMA接口之间有一条直接数据通路。由于DMA方式传送数据不需要经过CPU,因此不必中断现行程序,I/O与主机并行工作,程序和传送并行工作。 2.DMA控制器的组成 对数据传送过程中进行控制的硬件称为DMA控制器(DMA接口)。 当I/O设备需要进行数据传送时,通过DMA控制器向CPU提出DMA传送请求,CPU响应之后让出系统总线,由DMA控制器接管总线进行数据传送。 1)接受外设发出的DMA请求,并向CPU发出总线请求。 DMA请求触发器:每当I/O设备准备好数据后给出一个控制信号,使DMA请求触发器置位。 由此可见,DMA控制器必须具有控制系统总线的能力。 3.DMA的传送方式 主存和DMA控制器之间有一条数据通路,因此主存和I/O设备之间交换信息时。不通过CPU。
直接内存访问(Direct Memory Access,DMA):在计算机体系结构中,DMA 是一种数据传输方式,允许外部设备直接访问计算机的内存,而无需通过中央处理单元(CPU)的干预。 那么,DMA究竟有多快呢? 实践出真知 恰好,最近有个多通道数据采集的项目,受限于通道数多、分辨率高,而系统带宽有限,为了尽可能充分利用有限带宽,就得想办法优化时序,把时间都留给数据采集和传输。 优化方向就是DMA。 硬件链路是ADC通过SPI接口将数据发送给STM32单片机,单片机再将数据发送到上位机。 咱们的目标就是优化SPI这边,先看普通采集模式。 再看下,开启DMA之后的效果。SPI可以连续工作,时钟速率稳定在20MHz,高效工作。 这就是DMA的强大之处! 问题来了,为什么上图中的波形,有这么大的震荡呢?
如SDRAM, QSPI,SPI等,H743里面DMA比较多,也较复杂,有DMA2D,MDMA, BDMA,DMA1,DMA2等等,使用时候注意区分。 MDMA 先来看看MDMA的框图概览 ? DMA H743有两个DMA,分别为DMA1和DMA2, ? ? ? 像ADC,UART,SPI,SD卡等外设都支持DMA传输和操作,都有相应例程,比如我在SPI和另一个芯片通信就使用DMA2来传输。 ? ? DMA的知识和篇章在参考手册中有很多介绍需要详细阅读和参考,结合例程。 DMA2D DMA2D是专门用于图像处理加速的DMA,我们在做屏的驱动时候可以充分考虑使用。 ? 手册中有几十页都是来讲DMA2D的,这个功能还是很好的,如果你使用H743做屏幕类相关产品,这个要用起来。例如我在移植emWIN作为图形界面时候驱动就使用了DMA2D. ? ?
惠伟:IOMMU(三)-初始化zhuanlan.zhihu.com DMA remapping就是在DMA的过程中IOMMU进行了一次转换,MMU把CPU的虚拟地址(va)转换成物理地址(pa),IOMMU 的作用就是把DMA的虚拟地址(iova)转换成物理地址(pa),MMU转换时用到了pagetable,IOMMU转换也要用到io pagetable,两者都是软件负责创建pagetable,硬件负责转换 IOMMU的作用就是限制DMA可操作的物理内存范围,当一个PCI设备passthrough给虚拟机后,PCI设备DMA的目的地址是虚拟机指定的,必须要有IOMMU限制这个PCI设备只能操作虚拟机用到的物理内存 DMA类型 Requests without address-space-identifier DMA中只带了source-id,也就是PCI设备的bus/dev/funtion。 passthrough translation 跳过转换,DMA的iova就是pa。 IOMMU工作模式 intel vt-d iommu可以工作于legacy和scale模式。
Programming工作模式: 1.首先验证CDMASR.IDLE=1(开始写) 2.如果传输完成,则产生CDMACR.IOC_IrqEn中断请求,否则产生错误 3.写源地址寄存器SA 4.写目的地
DMA 技术: DMA 技术,也就是直接内存访问(Direct Memory Access) 技术。 DMA 技术:在进行 I/O 设备和内存的数据传输的时候,数据搬运的工作全部交给 DMA 控制器, 而 CPU 不再参与任何与数据搬运相关的事情,这样 CPU 就可以去处理别的事务。 执行其他任务; 3、DMA 进一步将 I/O 请求发送给磁盘; 4、磁盘收到 DMA 的 I/O 请求,把数据从磁盘读取到磁盘控制器的缓冲区中,当磁盘控制器的缓冲区被读满后, 向 DMA 发起中断信号 ,告知自己缓冲区已满; 5、DMA 收到磁盘的信号,将磁盘控制器缓冲区中的数据拷贝到内核缓冲区中,此时不占用 CPU,CPU 可以执行其他任务; 6、当 DMA 读取了足够多的数据,就会发送中断信号给 CPU; 7、CPU 收到 DMA 的信号,知道数据已经准备好,于是将数据从内核拷贝到用户空间,系统调用返回;
APP viewpoint SMMU config dma alloc SMMU dma_alloc_coherent DMA buf vs smmu iommu_probe_device
05 STM32少个DMA资源? 对于大容量的STM32芯片有2个DMA控制器,DMA1有7个通道,DMA2有5个通道。每个通道都可以配置一些外设的地址。 在这里插入图片描述 有DMA传输: 有DMA的话, DMA传输时外设对DMA控制器发出请求。 DMA控制器收到请求,触发DMA工作。 07 DMA传输方式 方法1:DMA_Mode_Normal,正常模式 当一次DMA数据传输完后,停止DMA传送 ,也就是只传输一次。 当设置了DMA_CCRx寄存器中的MEM2MEM位之后,在软件设置了DMA_CCRx寄存器中的EN位启动DMA通道时,DMA传输将马上开始。当DMA_CNDTRx寄存器变为0时,DMA传输结束。 17 DMA中断标志清除寄存器 (DMA_IFCR) DMA_IFCR 的各位就是用来清除 DMA_ISR 的对应位的,通过写 0 清除。
DMA有两种工作方式:Block DMA(传统的普通DMA)和Scatter-Gather DMA。 Block DMA一次DMA传输只能处理一个物理上连续的内存区域; 而Scatter-Gather DMA单次DMA传输可以处理多个物理上不连续的内存区域,这些不联系的内存区域用一个链表描述,DMA得到链表首地址后 三、Linux内核中的DMA Linux中有两类关键的DMA框架:DMA mapping和DMA Engine。 接口有dma_map_single、dma_unmap_single、dma_map_sg、dma_unmap_sg等。 DMA Engine 提供统一的 API 接口、事务调度、通道管理、中断分发逻辑,外设驱动可调用 DMA Engine 提供的标准化 API,发起 DMA 传输请求,具体DMA 控制器驱动可通过DMA
综上,在ZYNQ中DMA和AXI是不可分割的两者,所以介绍DMA也是必须的。 使用DMA时,CPU向DMA控制器发送一个存储器传输请求,这样当DMA控制器在传输的时候,CPU执行其他的操作,传输完成时DMA以中断的方式通知CPU。 DMA传输过程的示意图为: ? 图4‑35 DMA传输过程的示意图 DMA的传输过程为: 1、为了配置用DMA传输数据到存储器,处理器(Cortex-A9)发出一条指令。 而DMA就不同了,一般系统中的DMA都有突发(Burst)传输的能力,在这种模式下,DMA能一次传输几个甚至几十个字节的数据,所以使用DMA能使设备的吞吐能力大为增强。 DMAC为DMA控制器 DMA传送虽然脱离CPU的控制,但并不是说DMA传送不需要进行控制和管理。通常是采用DMA控制器来取代CPU,负责DMA传送的全过程控制。
(); //配置DMA中断 /*设置DMA源:内存地址&串口数据寄存器地址*/ DMA_InitStructure.DMA_PeripheralBaseAddr */ DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; /*外设数据单位*/ DMA_InitStructure.DMA_PeripheralDataSize ; /*DMA模式:一次传输,循环*/ DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ; /* DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; /*配置DMA1的4通道*/ DMA_Init(DMA1_Channel4 , &DMA_InitStructure); DMA_Cmd (DMA1_Channel4,ENABLE); //使能DMA
2、流式DMA映射(streaming DMA mapping) 流式DMA映射是一次性的,一般是需要进行DMA传输的时候才进行mapping,一旦DMA传输完成,就立刻ummap(除非你使用dma_sync dma pool就是通过dma_alloc_coherent接口获取大块一致性的DMA内存,然后驱动可以调用dma_pool_alloc从那个大块DMA内存中分一个小块的dma buffer供自己使用。 七、DMA操作方向 由于下面的章节会用到DMA操作方向这个概念,因此我们先简单的描述一下,DMA操作方向定义如下: DMA_BIDIRECTIONAL DMA_TO_DEVICE DMA_FROM_DEVICE 示例代码一: dma_addr_t dma_handle1; dma_addr_t dma_handle2; dma_handle1 = dma_map_single(dev, addr, size, dma buffer,当在中间出错的时候,一样要unmap所有已经映射的dma buffer): dma_addr_t dma_addr; dma_addr_t array[DMA_BUFFERS];
DMA 参与下的数据四次拷贝 DMA 技术很容易理解,本质上,DMA 技术就是我们在主板上放一块独立的芯片。 在进行内存和 I/O 设备的数据传输的时候,我们不再通过 CPU 来控制数据传输,而直接通过 DMA 控制器(DMA Controller,简称 DMAC)。 原本,计算机所有组件之间的数据拷贝(流动)必须经过 CPU,如下图所示: 现在,DMA 代替了 CPU 负责内存与磁盘以及内存与网卡之间的数据搬运,CPU 作为 DMA 的控制者,如下图所示: 但是 利用 DMA 技术 sendfile 依赖于 DMA 技术,将四次 CPU 全程负责的拷贝与四次上下文切换减少到两次,如下图所示: 利用 DMA 技术减少 2 次 CPU 全程参与的拷贝 DMA 负责磁盘到内核空间中的 总结 DMA 技术的推出使得内存与其他组件,例如磁盘、网卡进行数据拷贝时,CPU 仅仅需要发出控制信号,而拷贝数据的过程则由 DMA 负责完成。
DMA remapping就是在DMA的过程中IOMMU进行了一次转换,MMU把CPU的虚拟地址(va)转换成物理地址(pa),IOMMU的作用就是把DMA的虚拟地址(iova)转换成物理地址(pa), IOMMU的作用就是限制DMA可操作的物理内存范围,当一个PCI设备passthrough给虚拟机后,PCI设备DMA的目的地址是虚拟机指定的,必须要有IOMMU限制这个PCI设备只能操作虚拟机用到的物理内存 DMA类型 Requests without address-space-identifier DMA中只带了source-id,也就是PCI设备的bus/dev/funtion。 Requests with address-space-identifier DMA中除了source-id还有PASID,而这个PASID来自于PCIE config space中的PASID Capability passthrough translation 跳过转换,DMA的iova就是pa。 IOMMU工作模式 intel vt-d iommu可以工作于legacy和scale模式。
此类型可以保存平台的任何有效 DMA 地址,并且应该在保存从 DMA 映射函数返回的 DMA 地址的任何地方使用。 什么内存支持 DMA? 这同样适用于 dma_map_page() 当 DMA 活动完成时,您应该调用 dma_unmap_single(),例如,从通知您 DMA 传输已完成的中断中调用 dma_unmap_single() 因为 dma_map_page() 可能会失败并返回错误,如 dma_map_single() 讨论中所述 当 DMA 活动完成时,您应该调用 dma_unmap_page(),例如,从通知您 DMA 返回 0 使用 dma_mapping_error() 检查从 dma_map_single() 和 dma_map_page() 返回的 dma_addr_t, 如: dma_addr_t dma_handle 这些示例也适用于 dma_map_page() Example 1:: dma_addr_t dma_handle1; dma_addr_t dma_handle2; dma_handle1
一致性DMA映射 dma_addr_t dma_handle; cpu_addr = dma_alloc_coherent(dev, size, &dma_handle, gfp); 这个函数返回两个值 __dma_alloc static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t static void *__dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t 比如DMA传输完成之后,CPU去把这个DMA buffer的数据取过来,这时候cache关闭的,CPU去读写就变得很慢。 这里介绍个即可以保证DMA传输的一致性,又能提高性能的方法:流式DMA映射。 dma_map_single流程如下:dma_map_single dma_map_single_attrs ops->map_page 没有iommu的话会走__swiotlb_map_page。
STM32F4 最多有 2 个 DMA 控制器(DMA1 和 DMA2),共 16 个数据流(每个控制器 8 个),每一个 DMA 控制器都用于管理一个或多个外设的存储器访问请求。 双缓冲区模式 我们可以理解为,两个数据流同时操作,比如DMA1在传输的时候,去填充DMA2的数据,等DMA1完成后,DMA2就接上DMA1的数据流继续发送。 void DMA_Init(DMA_Stream_TypeDef* DMAy_Streamx, DMA_InitTypeDef* DMA_InitStruct); 3、使能串口 1 的 DMA 发送 ;//外设非增量模式 DMA_InitStructure.DMA_Priority = DMA_Priority_Low; //低优先级 DMA_Init(DMA_Streamx, &DMA_InitStructure );//初始化DMA Stream } //开启一次DMA传输 //DMA_Streamx:DMA数据流,DMA1_Stream0~7/DMA2_Stream0~7 //ndtr:数据传输量
DMA buffer create NVMAP MALLOC dma buf attach dma buffer map attachment DMA buffer unmap attachment DMA buffer release subsytem release dma buffer subsytem map dma buffer one use case
DMA 通道的 DMA 缓存的大小,单位为数据单位。 // DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular DMA_Init(DMA1_Channel1, &DMA_InitStructure); //使能DMA DMA_Cmd (DMA1_Channel1 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular DMA_Init(DMA1_Channel4, &DMA_InitStructure); //使能DMA DMA_Cmd (DMA1_Channel4