zoukankan      html  css  js  c++  java
  • 和菜鸟一起学linux总线驱动之DMA传输

        最早接触DMA的时候是大三的微机原理,当时不是很理解,什么DMA模式啊,只知道是传输速度快,不经过CPU,但是到底是怎么样的不经过CPU呢?还是不理解。这次I2C控制器里面带了DMA的模式,所以有机会去接触下了。

           而具体的DMA的意思是什么http://baike.baidu.com/view/32471.htm,百度百科里还是不错的。

     

    DMA的工作过程:

     

           对于嵌入式中的DMA,其实是在写数据寄存器的时候用dma的传输来代替。就像i2c设备,在发送和接收数据的时候都是要往数据寄存器中写数据的。比如那个寄存器是I2C_DATA,如果用cpu来传输的话就是writel(data, I2C_DATA);而用dma传输就是配置好要传输的buf长度,然后源地址就是buf的地址,目标地址就是I2C_DATA。

           这里还要注意经过cpu的是虚拟地址,而dma传输的是物理地址。

           其实dma传输就是dma控制在两个物理地址之间传输数据。

     

    Linux下用dma传输主要调用下面这些函数就可以实现外部的dma了。

     

    具体的就可以看下面简单的解释,以下主要是dma发送的,其实接收也一样的。配置反一下就可以了。

    1、初始化DMA

     dma_cap_zero(mask);
           dma_cap_set(DMA_SLAVE,mask);
     
           /*1. Init rx channel */
           dws->rxchan= dma_request_channel(mask, dma_chan_filter, params);
           主要就是申请DMA通道。
     
           dma_chan_filter这个函数主要是查找你的dma传输的设备的请求信号线,其具体是在注册时填写的。
    这里会根据这个函数返回的真假来判断已经注册在总线上的dma slave的。
     
     
    buf =kmalloc(DMA_BUFFER_SIZE, GFP_KERNEL);
    //申请一块地址,用来DMA传输的数据就放在这里
    sg_init_one(&dma_dev->dmatx.sg,  buf,  DMA_BUFFER_SIZE);
           //初始化,其主要为了发送时虚拟地址和物理地址的映射。

     

    2、启动DMA

    struct dma_async_tx_descriptor *txdesc = NULL;
           struct dma_chan *txchan,;
           struct dma_slave_config txconf;
     
           txchan= dws->txchan;
          
           /*2. Prepare the TX dma transfer */
           txconf.direction= DMA_TO_DEVICE;              //表示dma传输方向为发送
           txconf.dst_addr= dws->dma_addr;                   //目标地址,物理地址
           txconf.dst_maxburst= LNW_DMA_MSIZE_16; //最大传输的字节数
           txconf.dst_addr_width= DMA_SLAVE_BUSWIDTH_2_BYTES;  //数据的位宽
     
           txchan->device->device_control(txchan,DMA_SLAVE_CONFIG,
                                       (unsigned long) &txconf);
          
           dws->tx_sgl.length= dws->len;    //要传输的数据的长度
     
    dma_map_sg(dma_dev->dev,&dmatx->sg, 1, DMA_TO_DEVICE);
    //通过这个函数来实现虚拟地址和物理地址的映射。
     
           txdesc= txchan->device->device_prep_slave_sg(txchan,
                                &dws->tx_sgl,
                                1,
                                DMA_TO_DEVICE,
                                DMA_PREP_INTERRUPT| DMA_COMPL_SKIP_DEST_UNMAP);
           txdesc->callback= dw_spi_dma_done;   //传输完成后的回调函数
           txdesc->callback_param= params;      //回调函数中的参数
     
           dmaengine_submit(txdesc);
    dma_dev->device_issue_pending(txchan); // 启动dma传输了
          

    配置好后,这样DMA就会开始传输了,然后传输完了以后就会有调用callback函数。

     

     

  • 相关阅读:
    左孩子右兄弟的字典树
    UVA 1401 Remember the Word
    HDOJ 4770 Lights Against Dudely
    UvaLA 3938 "Ray, Pass me the dishes!"
    UVA
    Codeforces 215A A.Sereja and Coat Rack
    Codeforces 215B B.Sereja and Suffixes
    HDU 4788 Hard Disk Drive
    HDU 2095 find your present (2)
    图的连通性问题—学习笔记
  • 原文地址:https://www.cnblogs.com/wuyida/p/6300030.html
Copyright © 2011-2022 走看看