s3c2440a 裸奔2之直接存储器存取DMA
- 格式:pdf
- 大小:1.01 MB
- 文档页数:28
直接存储器存取DMA一、 概述:S3c2440a支持四通道系统总线和外设总线间的DMA控制器。
每个通道都可以处理以下四种情况:1.源和目标都在系统总线上。
2.当源在系统总线上时,目标在外设总线上3.当源在外设总线上时,目标在系统总线上4.源和目标都在外设总线上DMA的主要优点是在没有CPU干预的情况下可以进行数据传输,DMA的运行可以由软件开始,可以由内部的外设或者外部引脚的请求开始。
二、 DMA请求源:如果选择硬件DMA,那么每个DMA通道都可以选择DMA请求源中的一个,倘若设置了软件请求模式,则每个DMA 通道就不能选择了,以下图表为可供DMA通道选择的请求源列表:三.DMA操作:DMA为其运行使用3态FSM(有限状态机),具体过程见如下描述1.作为初始状态DMA等待DMA请求,一旦等到DMA 请求则进入第二状态,在此状态时DMA ACK和INT REQ为0 2.在此状态,DMA ACK 变为1 而且计数器(CURR_TC)从DCON[19:0]寄存器中加载。
注意DMA ACK 保持为1 直到之后将其清除。
3.在此状态,处理DMA 的原子操作的sub-FSM 启动。
sub-FSM 从源地址读取数据,接着写入目标地址。
在此操作中考虑数据大小和传输大小(单次或突发)。
此操作在全服务模式中一直重复直到计数器(CURR_TC)变为0,在单服务模式只执行一次。
当sub-FSM完成了每个原子操作时主FSM(此FSM)倒计数CURR_TC。
此外当CURR_TC 变为0 并且DCON[29]寄存器的中断设置置位为1 时主FSM 发出INT REQ 信号。
另外如果遇到以下状况之一则清除了DMA ACK。
1) 在全服务模式中CURR_TC 变为0;2) 在单服务模式中完成原子操作。
注意在单服务模式中有三个主FSM 的状态要执行并且接着要停止和等待其它DMA REQ。
如果DMA REQ 出现了要重复所有的三个状态。
所以发出DMA ACK 并接着取消原子传输。
与之对比,在全服务模式中,主FSM 在状态3 中等待直到CURR_TC 变为0。
所以在所有传输期间发出DMA ACK 并接着在当TC 到达0 时取消。
总之当且仅当在CURR_TC 变为0 时才发出INT REQ,与服务模式(单顾服务模式或全顾服务模式)无关。
四.外部DMA请求/应答(DREQ/DACK)协议:三种DMA请求/应答协议类型:1)单服务查询 2)单服务握手 3)全服务握手 单服务查询时序图:单服务握手时序图:全服务握手时序图:五.DMA特殊寄存器1.DMA初始源(DISRC)寄存器2.DMA初始源控制(DISCC)寄存器3.DMA目标源(DIDST)寄存器4.DMA目标源控制(DIDSTC)寄存器5.DMA控制(DCON)寄存器6.DMA状态(DSTAT)寄存器:7.DMA当前源(DCSRC)寄存器8.DMA当前目标(DCDST)9.DMA触发屏蔽(DMASKTRIG)寄存器应用实例:以下内容转载自网络,有内容有程序,实际上通过这个转载资料让我们很好的体会了DMA的具体作用,稍后我会自己写一个DMA应用程序,奉献给大家。
呵呵DMA(Direct Memory Access,直接内存访问)是一种不经过CPU而直接从内存存取数据的数据交换模式。
在需要进行大量数据交换的场合,用好DMA,可以大大提高系统的性能,因为DMA操作几乎不占用CPU资源。
s3c2440提供了4个通道的DMA,它们不仅可以实现内存之间的数据交换,还可以实现内存与外设,以及外设与外设之间的数据交换。
要用好s3c2440的DMA,关键是配置好它的源、目的寄存器,和必要的控制寄存器。
寄存器DISRCn是初始DMA源寄存器,它是用于设置DMA数据传输的源基址,而寄存器DIDSTn是初始DMA目的寄存器,它是用于设置DMA数据传输的目的基址。
初始DMA源控制寄存器DISRCCn的第1位用于选择源的总线(系统总线AHB还是外设总线APB),第0位用于设置源基址在数据传输过程中是递增还是固定不变。
初始DMA目的控制寄存器DIDSTCn的低两位与寄存器DISRCCn相识,但它是用来设置目的基址,而第2位用于设置是在传输完数据之后中断还是在自动重载后中断。
DMA控制寄存器DCONn用于控制数据的DMA传输,第31位用于设置传输协议是需求模式还是握手模式,第30位用于选择同步时钟是PCLK还是HCLK,第29位用于设置DMA中断是否发生,第28位用于选择传输大小是单元传输还是突发传输,第27位用于选择服务模式是单步模式还是完全模式,第24位到第26位用于设置DMA的请求源,第23位用于设置DMA的源是软件还是硬件,第22位用于设置是否需要重载传输的目的和源基址,第20位和第21位用于设置数据传输的数据大小(字节、半字还是字),低20位用于初始化传输数据的个数。
而通过读取DMA状态寄存器DSTATn的低20位可以获知当前的传输的计数。
DMA掩码触发寄存器DMASKTRIGn的第2位可以终止当前DMA操作,第1位可以用于开启DMA通道,第0位则表示在软件请求模式下触发DMA通道。
下面我们就用DMA的方式来实现音频的播放。
由于是用DMA的方式,因此在播放的过程中不占用系统资源,我们可以很容易的实现声音的各种操作而丝毫不影响播放的效果,如音量的提高和降低、静音、暂停等。
在这里,还需要强调一点,利用DMA传输数据,一次最多可以传输的字节大小为:DSZ×TSZ×TC,DSZ表示的是数据大小(字节、半字还是字,即是1、2还是4),TSZ表示的是传输大小(单元传输还是突发传输,即1还是4),TC表示传输计数值(即寄存器DCONn的低20位存放的数据),因此如果需要传输的字节大小超出了这三个参数乘积的大小,则还要进一步处理,在我们给出的程序中,我们就考虑了这方面的问题。
下面就是具体的程序,其中我们是利用UART来实现音频信号的播出、停止、暂停、静音、音量的提高和降低的。
以下为程序范例:…… ……//一段纯音频数据数组unsigned char music[] = {0xF9, 0xFF, 0xF5, 0xFF, 0xF8, 0xFF, 0xF8, 0xFF, 0xF6, 0xFF, 0xFF, 0xFF, 0xF5, 0xFF, 0xF9, 0xFF,0xF6, 0xFF, 0xF6, 0xFF, 0xFA, 0xFF, 0xFD, 0xFF, 0xFA, 0xFF, 0xFA, 0xFF, 0xF7, 0xFF, 0xF6, 0xFF,…… ……};int result;int remainder;char flag;char cmd;char play_state;void __irq uartISR(void){char ch;rSUBSRCPND |= 0x1;rSRCPND |= 0x1<<28;rINTPND |= 0x1<<28;ch=rURXH0;switch(ch){case 0x55: //播放 cmd = 1;break;case 0x1: //静音cmd = 0x11;break;case 0x2: //音量提高 cmd = 0x12;break;case 0x3: //音量降低 cmd = 0x13;break;case 0x66: //停止cmd = 0x2;break;case 0x77: //暂停cmd = 0x3;break;}rUTXH0=ch;}//放音子程序void playsound(unsigned char *buffer,int length){//用于计算音频数据的长度是否超过DMA所能传输的字节数范围 //这里音频数据的通道位数为16位,因此需要length除以2remainder = (length>>1) & 0xfffff; //余数result = (length>>1) / 0x100000; //商play_state = 1; //置播放标志rGPBDAT = rGPBDAT & ~(L3M|L3C|L3D) |(L3M|L3C);//配置1341,详细讲解请看上一篇文章WriteL3(0x14 + 2,1);WriteL3(0x60,0);WriteL3(0x14 + 2,1);WriteL3(0x10,0);WriteL3(0x14 + 2,1);WriteL3(0xc1,0);//配置IISrIISPSR = 3<<5|3;rIISCON = (1<<5)|(0<<4)|(0<<3)|(1<<2)|(1<<1); //发送IIS的DMA使能rIISMOD = (0<<9)|(0<<8)|(2<<6)|(0<<5)|(0<<4)|(1<<3)|(1<<2)|(1<<0);rIISFCON = (1<<15)|(1<<13); //发送FIFO为DMA//配置DMArDISRC2 = (U32)buffer; //DMA的源基址为音频数据数组的首地址rDISRCC2 = (0<<1)|(0<<0); //AHB,源地址递增rDIDST2 = (U32)IISFIFO; //DMA的目的基址为IIS的FIFOrDIDSTC2 = (0<<2)| (1<<1)|(1<<0); //当传输计数值为0时中断,APB,目的地址不变if (result == 0) //所传输的字节数没有超出DMA的最大传输范围{flag = 0; //清标志,表示没有超出范围,进入DMA中断后结束DMA操作//握手模式,PCLK同步,传输计数中断,单元传输,单步服务模式,IISSDO,//硬件请求模式,非自动重载,半字,rDCON2 = (1<<31) | (0<<30) | (1<<29) | (0<<28) | (0<<27) | (0<<24) | (1<<23) | (1<<22) | (1<<20) | (remainder); }else //所传输的字节数超出了DMA的最大传输范围{flag = 1; //置标志,表示超出范围rDCON2 = (1<<31) | (0<<30) | (1<<29) | (0<<28) | (0<<27) | (0<<24) | (1<<23) | (1<<22) | (1<<20) | (0xfffff); }rDMASKTRIG2=(0<<2)|(1<<1)|0; //不停止DMA,DMA通道开启,非软件触发//启动IISrIISCON |= 0x1;}void __irq DMA_end(void){rSRCPND |= 0x1<<19;rINTPND |= 0x1<<19;if (flag == 0) //DMA传输完毕{rIISCON = 0x0; //关闭IISrIISFCON = 0x0; //清IIS的FIFOrDMASKTRIG2=1<<2; //停止DMAplay_state = 0; //清播放标志}else //DMA没有传输完毕,继续传输{result --; //商递减rDISRC2 += 0x200000; //DMA源基址递增。