Chinaunix首页 | 论坛 | 博客
  • 博客访问: 241567
  • 博文数量: 41
  • 博客积分: 928
  • 博客等级: 准尉
  • 技术积分: 550
  • 用 户 组: 普通用户
  • 注册时间: 2011-04-01 10:07
文章分类
文章存档

2011年(41)

分类: 嵌入式

2011-04-17 16:55:22

转载:http://blog.csdn.net/cybertan/archive/2009/10/19/4697516.aspx

DMA优点是其进行数据传输时不需要CPU的干涉,可以大大提高CPU的工作效率。

DMA大容量数据传输中非常重要,比如图像数据传输,SD卡数据传输,USB数据传输等等。

S3C2410有四个DMA,每个DMA支持工作方式基本相同,但支持的source Dest可能略有不同。

那么怎么使用DMA呢,S3C2410内部集成了DMA控制器,我们只需要简单的配置一下寄存器就可以实现DMA的传输了。

步骤与要点:

1.       数据从哪里来,到哪里去?

使用DMA当然首先我们要知道数据的流向,DISRCx寄存器是DMA初始源寄存器存放了数据的源地址。DIDSTxDMA的初始目的寄存器,应该存放数据的目的地址。

 

2.       数据走得什么总线?地址是否是固定的?

我们还要知道源与目的数据存储设备是在什么总线上(AHB系统总线,一般是高速的比如内存,APB外围总线低速的,比如SDUART);

以及数据传输结束以后起始地址还原到发送前的起始地址呢,还是在现在的末尾+1做为新的起始地址。

这些设置在DISRCCxDIDSTCx两个寄存器里面配置。

 

3.       数据以什么方式传输?源与目的是什么设备?要不要自动重载?

需要确定数据的传输方式有请求还是握手(推荐使用HANDSHAKE,根据上面的总线确定与什么时钟同步(HCLKPCLK),是单元传输还是突发传输,是以字节传输还是字传输,是否重载。是单服务(只发送一次)还是多服务(不停循环发送),以及数据的传送大小。

选择源与目的设备,这里DMA控制器支持:

   Ch0:nXDREQ0,UART0,SDI,Timer,USB EP1

   Ch1: nXDREQ1,UART1,I2SSDI,SPI0,USB EP2

   Ch2:I2SSDO,I2SSDI,SDI,Timer, USB EP3

   Ch3:UART1,SDI,SPI1,Timer, USB EP4

最后还要确定中断是不是传输结束发生(CURR_TC记数是不是0)。

这些都在DCONx中设置。

4.       怎么开始传输DMA和停止DMA,这些在DMASKTRIG中设置。

 

下面是DMASD卡中使用的一段示例:

 

SD卡读的DMA设置:

pISR_DMA0=(unsigned)DMA_end; //DMA中断服务函数入口地址,一次DMA传送结束发生rINTMSK = ~(BIT_DMA0); //DMA中断

rDISRC0=(int)(Tx_buffer); //源地址在内存 就是从内存读数据到SD

rDISRCC0=(0<<1)+(0<<0); //内存的总线是 AHB, 地址是自动增加inc

rDIDST0=(U32)(SDIDAT); // 目的地址SD

rDIDSTC0=(1<<1)+(1<<0); // 在总线APB, 地址是固定的因为SDFIFO是固定大的  

rDCON0=(1<<31)+(0<<30)+(1<<29)+(0<<28)+(0<<27)+(2<<24)+(1<<23)+(1<<22)+(2<<20)+128*block;

//handshake握手模式 PCLK同步,发送完产生中断单元传输单服务, SDI

//不自动重载,每次发送一个字,发送大小

rDMASKTRIG0=(0<<2)+(1<<1)+0; //不停止, DMA0 channel 启动,不用SW触发

 

SD卡写的相应代码

pISR_DMA0=(unsigned)DMA_end;

rINTMSK = ~(BIT_DMA0);

rDISRC0=(int)(Tx_buffer);                             

rDISRCC0=(0<<1)+(0<<0);                           

rDIDST0=(U32)(SDIDAT);                             

rDIDSTC0=(1<<1)+(1<<0);                            

rDCON0=(1<<31)+(0<<30)+(1<<29)+(0<<28)+(0<<27)+(2<<24)+(1<<23)+(1<<22)+(2<<20)+128*block;                                                        

rDMASKTRIG0=(0<<2)+(1<<1)+0;

阅读(1403) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~