DMA子是CPU中实现数据传输的一种方式,CPU配置好DMA控制器之后发起数据传输,CPU本身不参与数据传输的动作中去。

DMA种类:
分为外设DMA和DMA控制器。其中外设DMA实现的为特定的外设与内存之间的数据传输,一般是外设向RAM单向传输数据。而DMA控制器则可以实现任意外设与内存之间的数据传输。此时外设跟CPU控制器之间通过流控制信号来保证传输通道的正常运行。

DMA传输的数据宽度不固定。

还可以实现任意长度的burst 操作。burst是DMA控制地址总线自行改变。

DMA也支持分散集合模式,即内存中数据并非连续,而是分配在多个块中,块大小也不一样,这时候DMA可以根据Scatter Gather Descriptors来进行DMA数据传输。

Descriptors是一个单向列表,描述了每块数据的位置和大小还有其他配置。DMA自行解析Descriptors的内容进行数据传输并寻找小一个链表节点,

如果Descriptor 链表是一个循环链接,则传输被叫做环形传输(Cyclic Transfers)。

linux实现了DMA框架,叫做DMA Engine,内核驱动开发者必须按照固定的流程编码才能正确的使用DMA。DMA Engine提供出来了Slave API供其它内核调用。这些API实现了复杂的scatter gather 传输模式,通过这些API实现DMA传输的驱动被叫做DMA client.

DMA中调用API的顺序为:

DMA通道申请

DMA client的第一步就是要申请DMA 通道,有的DMA client 可能需要申请特殊的通道,而有的DMA client可以申请任意可用的通道。通道申请的API为dma_request_channel 或者他的某一变形API。

struct dma_chan *dma_request_channel(dma_cap_mask_t mask, dma_filter_fn filter_fn, void *filter_param);

其中dma_cap_mask_t是根据dma_cap_sets指定的DMA传输类型。
如:

    dma_cap_mask_t mask;dma_cap_zero(mask);dma_cap_set(DMA_MEMCPY,mask);dma_chan1 = dma_request_channel(mask,0,NULL);

而传输类型具体列为:

enum dma_transaction_type {DMA_MEMCPY,DMA_XOR,DMA_PQ,DMA_XOR_VAL,DMA_PQ_VAL,DMA_MEMSET,DMA_INTERRUPT,DMA_SG,DMA_PRIVATE,DMA_ASYNC_TX,DMA_SLAVE,DMA_CYCLIC,DMA_INTERLEAVE,/* last transaction type for creation of the capabilities mask */DMA_TX_TYPE_END,};

配置DMA通道

dmaengine_slave_config
static inline int dmaengine_slave_config(struct dma_chan *chan,struct dma_slave_config *config)

获取一个传输描述符

dmaengine_prep_slave_single()

提交传输到挂起队列

dmaengine_submit

发起传输申请

dmaengine_issue_pending调用会从第一个描述符开始进行传输。如果DMA client 驱动有回调函数的话,会在传输完成后执行。

一个简单的DMA传输案例:

#include <linux/module.h>
#include <linux/kernel.h>    /* printk() */
#include <linux/moduleparam.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <linux/fs.h>
#include <linux/gfp.h>
#include <linux/cdev.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/mm.h>
#include <linux/kdev_t.h>
#include <linux/proc_fs.h>
#include <linux/ioctl.h>
#include <linux/slab.h>
#include <linux/mempool.h>
#include <linux/mm.h>
#include <linux/device.h>
#include <linux/kobject.h>
#include <linux/sysfs.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <asm/types.h>
#include <asm/io.h>
#include <asm/dma-mapping.h>#define DEST_ADDRESS 0x73800000
#define SRC_ADDRESS   0x10400000static volatile struct completion comp1;
static volatile struct dma_chan *dma_chan1;static int device_mmap(struct file *file,struct vm_area_struct* vma)
{int size;printk("mmap fpga\n");size=vma->vm_end - vma->vm_start;if(remap_pfn_range(vma,vma->vm_start,DEST_ADDRESS>>PAGE_SHIFT,0x800000,vma->vm_page_prot))return -EAGAIN;return 0;
}
static void dma_complete_func(void *completion)
{complete(completion);
}struct dma_async_tx_descriptor *tx1 = NULL;static int device_ioctl(struct inode *inode,struct file *file,int num,int param)
{struct dma_device *dma_dev;enum dma_ctrl_flags flags;dma_cookie_t cookie;dma_dev = dma_chan1->device;flags =  DMA_CTRL_ACK | DMA_COMPL_SKIP_DEST_UNMAP | DMA_COMPL_SKIP_SRC_UNMAP;tx1 = dma_dev->device_prep_dma_memcpy(dma_chan1, DEST_ADDRESS,SRC_ADDRESS+0x40000*param, 0x40000, flags);if (!tx1) {printk("Failed to prepare DMA memcpy\n");return -1;}init_completion(&comp1);tx1->callback = dma_complete_func;tx1->callback_param = &comp1;cookie = tx1->tx_submit(tx1);if (dma_submit_error(cookie)) {printk("Failed to do DMA tx_submit\n");return -1;}dma_async_issue_pending(dma_chan1);wait_for_completion(&comp1);
}static struct file_operations fpga_fops =
{.owner = THIS_MODULE,.mmap = device_mmap,.ioctl = device_ioctl,
};static int __init hello_init (void)
{dev_t fpga_dev;struct cdev *fpga_cdev;struct device *dev;dma_addr_t dm;dma_cap_mask_t mask;dma_cap_zero(mask);dma_cap_set(DMA_MEMCPY,mask);dma_chan1 = dma_request_channel(mask,0,NULL);if(dma_chan1 == 0){printk("fpga:failed to request DMA channel\n");}if(register_chrdev_region(MKDEV(200,0),1,"fpga")){printk (KERN_INFO "alloc chrdev error.\n");return -1;}fpga_cdev=cdev_alloc();if(!fpga_cdev){printk (KERN_INFO "cdev alloc error.\n");return -1;}fpga_cdev->ops = &fpga_fops;fpga_cdev->owner = THIS_MODULE;if(cdev_add(fpga_cdev,MKDEV(200,0),1)){printk (KERN_INFO "cdev add error.\n");return -1;}printk("fpga driver loaded\n");return 0;}late_initcall(hello_init);
MODULE_LICENSE("GPL");

dma子系统 dmac相关推荐

  1. 内存映射与DMA笔记

    内存映射与DMA笔记 2009-08-04 14:49 3项技术: 1,mmap系统调用可以实现将设备内存映射到用户进程的地址空间. 2,使用get_user_pages,可以把用户空间内存映射到内核 ...

  2. Linux内存管理:CMA(连续内存分配)(DMA)

    目录 什么是CMA 数据结构 CMA区域 cma_areas 的创建 dts方式 command line方式 将CMA区域添加到Buddy System CMA分配 <Linux内存管理:什么 ...

  3. 计算机组成原理DMA的全称,直接存贮器存取(DMA) -计算机组成原理与汇编语言-电子发烧友网站...

    5.4.1 DMA的工作过程 要实现DMA传送,目前都采用大规模集成电路芯片DMA控制器(DMAC). DMA的工作过程大致如下: ①外设向DMAC发出DMA传送请求. ②DMAC通过连接到CPU的H ...

  4. DMA PL330相关总结

    目录 一.DMA的介绍 二.PL330简述 三.工作原理 3.1 工作过程 3.2 传送的方式 四.PL330指令集 4.1 DMAMOV 4.2 DMALD 4.3 DMAST 4.4 DMARMB ...

  5. linux中的DMA提速1:各种内存分配验证

    前言 驱动需要优化驱动中的DMA速度.在此记录.使用DMA传输1280*800的数据就是1M字节. 使用外设的DMA功能,就需要给外设相应的DMA缓存寄存器设置一个地址,这个地址在内核中叫总线地址,而 ...

  6. DCS编程用C语言,如何用C语言对DMA控制器编程

    摘要:详细地分析了PC/AT机系统的DMA(直接存储器存取)控制器结构及其传输方式,并给出了C语言编程实例. DMA是英文DiretMemorAccess的缩写,即直接存储器存取,DMA传输是PC机与 ...

  7. S3C24XX DMA框架源码分析

    基于S3C2440 的DMA 框架源码分析 基于S3C2440 的DMA 框架源码分析 二寻根溯源 1 设备类的注册 2 s3c2410_dma_init 3 s3c24xx_dma_order_se ...

  8. PG195 DMA/Bridge Subsystem for PCI Express

    Introdction Xilinx® DMA/Bridge Subsystem for PCI Express® (PCIe®) 实现了一个高性能.可配置的 Scatter Gather DMA,用 ...

  9. Linux之DMA详解

    Linux之DMA详解 1.什么是DMA? DMA全称Direct Memory Access(直接访问存储器).这是指一种高速的数据传输操作,允许在外部设备和存储器之间直接读写数据. 2.为什么需要 ...

  10. ZYNQ从放弃到入门(九)-DMA

    ZYNQ从放弃到入门(九)-PS和PL交互-DMA 我们上一节谈到使用 DMA(直接内存访问)的好处已经变得显而易见.到了这一步,我们留下了人类长期以来一直在思考的问题:DMA到底是什么? DMA介绍 ...

最新文章

  1. php cli模式下获取参数的方法
  2. c语言扫描图片的坐标,tc 如何在指定坐标处 输出bmp图片??
  3. Plupload文件上传组件使用API
  4. Spring Boot 与 Java 对应版本,以下表格由官方网站总结。
  5. python开源项目贡献_如何通过为开源项目做贡献来发展自己的职业
  6. python计算机图形学_图形图像学习随笔:计算机图形学的一些基本概念
  7. minigui大号字体的实现,即ttf库的使用【转】
  8. PotPlayer:最强播放器,无边框
  9. 建自己的小屋真辛苦啊?!·##¥
  10. [小北De编程手记] : Lesson 01 玩转 xUnit.Net 之 概述
  11. ubuntu lamp环境(阿里云搭建lamp)
  12. 王者荣耀英雄铭文;出装
  13. 【单目标优化求解 】基于matlab烟花算法求解单目标问题【含Matlab源码 1599期】
  14. 大型网站架构:Flickr网站体系结构分析(转)
  15. WIN10 x64搭建OLLVM4.0 android NDK 编译环境跨坑指南
  16. Unity3D 实现本地排行榜功能
  17. h5物体拖动_HTML5原生拖拽/拖放(drag drop)详解
  18. Installing APK 'app-debug.apk' on 'OPPO R9m - 5.1' for app:debug
  19. 1700页!!我把 Java《八股文》肝完了...
  20. python等高线图平滑_用Matplotlib平滑等高线图中的数据

热门文章

  1. 通过uc_client接口方式,更新discuz会员头像
  2. 如何简单可靠地装系统-软碟通
  3. 《富爸爸穷爸爸》读书笔记 -- 第一章
  4. treefrog之视图 ERB
  5. 将List集合用字符串,逗号隔开进行拼接
  6. channel is not opened
  7. MOOC中国大学自动评分js脚本
  8. 《因子投资 - 方法与实践》新书上市
  9. 战略、战术(和 OKR)
  10. 无人驾驶入门——2D检测 基于图片的检测算法(四)