dma传输原理,及其linux总线驱动之DMA传输,

转载了他人的一篇文章,已表明转载的地址,如有侵权,请告知。

dma传输原理


1.DMA请求 
CPU对DMA控制器初始化,并向I/O接口发出操作命令,I/O接口提出DMA请求。  
2.DMA响应 
  DMA控制器对DMA请求判别优先级及屏蔽,向总线裁决逻辑提出总线请求。当CPU执行完当前总线周期即可释放总线控制权。此时,总线裁决逻辑输出总线应答,表示DMA已经响应,通过DMA控制器通知I/O接口开始DMA传输。  3.DMA传输 
  DMA控制器获得总线控制权后,CPU即刻挂起或只执行内部操作,由DMA控制器输出读写命令,直接控制RAM与I/O接口进行DMA传输。  
  在DMA控制器的控制下,在存储器和外部设备之间直接进行数据传送,在传送过中不需要中央处理器的参与。开始时需提供要传送的数据的起始位置和数据长度。  4.DMA结束 
  当完成规定的成批数据传送后,DMA控制器即释放总线控制权,并向I/O接口发出结束信号。当I/O接口收到结束信号后,一方面停 止I/O设备的工作,另一方面向CPU提出中断请求,使CPU从不介入的状态解脱,并执行一段检查本次DMA传输操作正确性的代码。最后,带着本次操作结果及状态继续执行原来的程序。  
  由此可见,DMA传输方式无需CPU直接控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为RAM与I/O设备开辟一条直接传送数据的通路,使CPU的效率大为提高。


Linux dma传输

下面转载了他人的一篇文章:

其中,也阐述了dma工作过程,看到有人说第一幅图错了,应该是首先dma请求总线。但是,我的理解是图没错。首先就是dma进行cpu请求,请求的目的是让cpu放弃总线控制。cpu只有放弃了总线控制权,给dma响应后,才能进行数据的传输。

---------------------------------------------------------------------------------------分--------------------割------------------------------线----------------------------------------------------------------

////转载的原文地址:http://blog.csdn.net/jk198310/article/details/8671866 

最早接触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

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

 

2、启动DMA

[html] view plaincopy
  1. struct dma_async_tx_descriptor *txdesc = NULL;  
  2.        struct dma_chan *txchan,;  
  3.        struct dma_slave_config txconf;  
  4.    
  5.        txchandws->txchan;  
  6.         
  7.        /*2. Prepare the TX dma transfer */  
  8.        txconf.directionDMA_TO_DEVICE;              //表示dma传输方向为发送  
  9.        txconf.dst_addrdws->dma_addr;                   //目标地址,物理地址  
  10.        txconf.dst_maxburstLNW_DMA_MSIZE_16; //最大传输的字节数  (转者注:这个参数应该是单次传输的字节长度
  11.        txconf.dst_addr_widthDMA_SLAVE_BUSWIDTH_2_BYTES;  //数据的位宽  
  12.    
  13.        txchan->device->device_control(txchan,DMA_SLAVE_CONFIG,  
  14.                                    (unsigned long) &txconf);  
  15.         
  16.        dws->tx_sgl.lengthdws->len;    //要传输的数据的长度  
  17.    
  18. dma_map_sg(dma_dev->dev,&dmatx->sg, 1, DMA_TO_DEVICE);  
  19. //通过这个函数来实现虚拟地址和物理地址的映射。  
  20.    
  21.        txdesctxchan->device->device_prep_slave_sg(txchan,  
  22.                             &dws->tx_sgl,  
  23.                             1,  
  24.                             DMA_TO_DEVICE,  
  25.                             DMA_PREP_INTERRUPT| DMA_COMPL_SKIP_DEST_UNMAP);  
  26.        txdesc->callbackdw_spi_dma_done;   //传输完成后的回调函数  
  27.        txdesc->callback_paramparams;      //回调函数中的参数  
  28.    
  29.        dmaengine_submit(txdesc);  
  30. dma_dev->device_issue_pending(txchan); // 启动dma传输了  
  31.         

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

发布了93 篇原创文章 · 获赞 31 · 访问量 22万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览