S3C2440的DMA

DMA,Direct Memory Access,直接存储器访问。其主要功能是在不需要处理器参与的情况下进行数据传输。值得一提的是,那些复杂的协议和时序图,是做DMA控制器的工程师要关心的事情;对于写使用DMA进行数据传输的工程师来说,只要稍微了解就可以了。

1. 简介

   S3C2440A有一个位于系统总线和外设总线间的4通道DMA控制器。每个通道都支持在位于系统总线上和(或)位于外设总线上的设备间进行无限制的数据传输。所谓“无限制的”,意思是每个通道可以处理四种情况:

(1)源和目标都在系统总线上

(2)源在系统总线上,目标在外设总线上

(3)源在外设总线上,目标在系统总线上

(4)源和目标都在外设总线上

   DMA的主要优点是可以在无需CPU干预的情况下进行数据传输。DMA传输可以由软件、内部外设请求或者外部请求引脚发起。

2. 请求源

   如果通过DCON寄存器设置了外部DMA请求模式,则DMA控制器的每个通道可以在6个请求源之间选择一个,见下表:

S3C2440的DMA - chengang-cn - AE-陈的技术中心

注意:只有在DCON[23]设置为1,表示使用硬件中断模式时,请求源才有效。

3. DMA有限状态机

DMA使用3状态的有限状态机来进行操作:

状态一:初始状态。DMA控制器等待DMA请求,DMA ACK和INT REQ都是0。一旦请求到达,则进入状态二。

状态二:ACK变为1,从DCON[19:0]装载传输计数值到CURR_TC。注意:ACK保持为1直到随后清除它。

状态三:在此状态下,初始化进行原子操作的子有限状态机。子有限状态机(sub-FSM)从源地址读取数据,写入到目的地址(原子操作)。这个操作会考虑数据尺寸和传输尺寸(单步还是突发)。在完全服务模式(whole service mode)下,此操作会重复直到传输计数值CURR_TC变为0;在单步服务模式下,此操作只进行一次。子有限状态机每完成一次原子操作,主有限状态机会让CURR_TC减1。如果CURR_TC变为0,又在DCON[29]设置了启用中断,则DMA控制器会发起DMA中断请求。此时,如果满足下列条件之一,还会清除DMA ACK:

(1)在完全服务模式下CURR_TC变为0

(2)在单步服务模式下原子操作完成

   在单步服务模式下,主有限状态机分别经历这三个状态一次,然后传输停止,等待下一个DMA请求。下一个请求到达时,会重复这三个状态一次。因此,对于每次原子操作,ACK都会被设置然后被清除。相反,在完全服务模式下,主有限状态机会保持在状态三直到CURR_TC变为0。在整个传输过程中,ACK保持为1,直到传输完成,ACK才变为0。然而,无论是单步服务模式还是完全服务模式,都只在CURR_TC变为0时才发起DMA中断请求。

4. 寄存器

    S3C2440A对于每个DMA通道有9个寄存器,4个通道共使用了36个寄存器。9个寄存器中有6个是控制寄存器,用于控制DMA传输;3个是状态寄存器,用于监测DMA传输状态。

    实际传输的字节数 = DCON[19:0] * DSZ * TSZ

    DCON[19:0]初始传输计数;DSZ = DCON[21:20],传输的数据单元尺寸,类似C标准库中fread()函数第二个参数;TSZ = DCON[28],0表示每次进行一个单元传输,1表示每次进行(突发的)4个单元传输。

    软硬件方式选择:

    DCON[23] = 0:软件方式,应该在源和目标地址寄存器中写入有效地址。

    DCON[23] = 1:硬件方式,由DCON[26:24]指明DMA请求源

    其他:

    DCON[29]表示是否在传输完成时发起DMA中断请求

    DCON[27]选择单步服务模式还是完全服务模式,一般单步服务模式仅用于调试,常用的是完全服务模式

    DCON[30]选择DREQ/ACK同步方式

    DCON[31]选择请求模式还是握手模式,建议使用握手模式

5. 程序

程序功能:用memcmp()函数来验证DMA传输是正确的。

#define DMA_SIZE 0xFFFFF
#define DMA_SRC (0x30A00000)
#define DMA_DST (0x31000000)

static volatile int dma_done;

static void __irq DMA_ISR()
{
rSRCPND = BIT_DMA0;
rINTPND = BIT_DMA0;
UART0_printf("\n##### End DMA Transfer #####\n");
dma_done = 1;
}

static void DMA_memcpy(void* p_dst,const void* p_src,int len)
{
rDISRC0 = ((int)p_src & 0x7FFFFFFF);
rDISRCC0 = 0;
rDIDST0 = ((int)p_dst & 0x7FFFFFFF);
rDIDSTC0 = 0;

rDCON0 = (len & 0xFFFFF) + (2 << 20) +
(1 << 22) + (1 << 27) + (1 << 29) + (1 << 30) + (1U << 31);
rDMASKTRIG0 = 0x03;
}

void DMA_Test()
{
pISR_DMA0 = (unsigned int)DMA_ISR;
rINTMSK &= (~BIT_DMA0);

memset((void*)DMA_DST,0,DMA_SIZE*4);
UART0_printf("BEFORE transfer memcmp = %d\n\n",memcmp((void*)DMA_SRC,(void*)DMA_DST,4*DMA_SIZE));

dma_done = 0;
UART0_printf("START DMA Transfer\n");
DMA_memcpy((void*)DMA_DST,(const void*)DMA_SRC,DMA_SIZE);
while(0==dma_done);

UART0_printf("\n\nAFTER transfer memcmp = %d\n\n",memcmp((void*)DMA_SRC,(void*)DMA_DST,4*DMA_SIZE));
}

from : http://blog.sina.com.cn/s/blog_56dee71a0100dwik.html~type=v5_one&label=rela_nextarticle



s3c2440学习系列6(dma 续)

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

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

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

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

步骤与要点:

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

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

 

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

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

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

这些设置在DISRCCx与DIDSTCx两个寄存器里面配置。

 

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

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

选择源与目的设备,这里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中设置。

 

下面是DMA在SD卡中使用的一段示例:

 

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, 地址是固定的因为SD的FIFO是固定大的 

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;

转自:http://hi.baidu.com/125580956/item/cd25ec0b1d3029e23499021c



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值