S3C2440-DMA

发布时间:2011-3-28 14:04    发布者:techshare
关键词: DMA , S3C2440
S3c2440A 支持位于系统总线和外设总线之间的4 个通道的控制器。每个DMA 控制器通道
无限制地执行系统总线上的设备或外设总线上的设备之间数据搬移。换句话说,就是每个
通道都操作一下四种情况:
(1)源和目的设备都在系统总线上
(2)源设备在系统总线上,目的设备在外设总线上
(3)源设备在外设总线上,目的设备在系统总线上
(4)源设备和目的设备都在外设总线上
DMA 的主要有点就是其传输数据不需要CPU 的干涉。DMA 操作可由软件或来自内设或外
部请求引脚来初始化。
DMA每次传送2个字节,放到FIFO中,IIS就播放,FIFO空,导致DMA被再次触发,直到传输计数器为0,产生DMA中断,CPU进入中断处理程序。在DMA传送的时候,CPU可以处理其他事情。提高了系统效率。

下面的程序使用IIS播放声音同时跑流水灯。如果不用DMA,直接用上一篇的IIS程序,会发现声音断断续续,因为IIS和流水灯一起分CPU的时间。如果使用DMA,则IIS需要的数据由DMA负责传送,而CPU可以执行流水灯程序,互相不耽误。当传输计数器为0时,产生DMA中断,CPU进入中断处理程序。其他时候,CPU可以执行流水灯。这样就实现了流水灯和IIS放音同时执行。


#include "2440addr.h"     
#include "music.h"     
#define L3MODE 1<<2     
#define L3DATA 1<<3     
#define L3CLOCK 1<<4   
#define _ISR_STARTADDRESS 0x33ffff00  
#define U32 unsigned int   
U32 flag, result, remain;   

void Delay(){
        int i, j, k;
        for(i = 0; i < 0xff; i++)
                for(j = 0; j < 0xff; j++)
                        for(k = 0; k < 0xff; k++)
                                ;
}

void Led(){
        int i;
        for(i = 3; i < 7; i++){
                rGPFDAT &= "(1<<i);
                Delay();
                rGPFDAT = 0xff;
        }
}

void WriteL3(unsigned char data, unsigned int mode){      
    //mode = 0,地址模式;mode = 1,数据传输模式      
    int i, k;      
    if(mode == 0){      
        rGPBDAT = rGPBDAT & "(L3MODE|L3DATA|L3CLOCK )|L3CLOCK;      
    }      
    else{      
        rGPBDAT = rGPBDAT & "(L3MODE|L3DATA|L3CLOCK)|(L3CLOCK|L3MODE);         
    }      
    for(k = 0; k < 5; k++)      
        ;      
    for(i = 0; i < 8; i++){      
        if(data & 0x1){      
            rGPBDAT &= "L3CLOCK;      
            rGPBDAT |= L3DATA;      
            for(k = 0; k < 5; k++)      
                ;         
            rGPBDAT |= L3CLOCK;      
            rGPBDAT |= L3DATA;      
            for(k = 0; k < 5; k++)      
                ;      
        }      
        else{      
            rGPBDAT &= "L3CLOCK;      
            rGPBDAT &= "L3DATA;      
            for(k = 0; k < 5; k++)      
                ;      
            rGPBDAT |= L3CLOCK;      
            rGPBDAT &= "L3DATA;      
            for(k = 0; k < 5; k++)      
                ;      
        }      
        data >>= 1;      
    }      
    rGPBDAT = rGPBDAT & "(L3MODE|L3DATA|L3CLOCK)|(L3CLOCK|L3MODE);      
}     
void PlayMusic(unsigned char buffer[], unsigned int length){      
    result = (length>>1)/0x100000;   
    remain = (length>>1)&0xfffff;      
    //UDA1341      
    //STATUS模式      
    rGPBDAT = rGPBDAT & "(L3MODE|L3DATA|L3CLOCK)|(L3CLOCK|L3MODE);      
    WriteL3(0x14+2,0);      
    //复位      
    WriteL3(0x60,1);      
    WriteL3(0x14+2,0);      
    //00010000 系统时钟频率384fs      
    WriteL3(0x10,1);      
    WriteL3(0x14+2,0);      
    //11000001 输出增益,ADC关,DAC开      
    WriteL3(0xc1,1);         
    //IIS      
    //DMA开启,在接受空闲状态,不产生IISLRCK信号,IIS预分频使能      
    rIISCON = (1<<5)|(0<<4)|(0<<3)|(1<<2)|(1<<1);      
    //主设备时钟PCLK,主设备模式,发送模式,串行数据16位,主时钟是384fs,串行位时钟32fs      
    rIISMOD = (0<<9)|(0<<8)|(2<<6)|(0<<5)|(0<<4)|(1<<3)|(1<<2)|(1<<0);      
    //预分频都是N=3        
    rIISPSR = (3<<5)|3;      
    //发送FIFO用DMA模式,发送FIFO使能      
    rIISFCON = (1<<15)|(1<<13);   
      
    //DMA   
    rDISRC2 =  (U32)buffer;                //DMA2初始源地址   
    rDISRCC2 = (0<<1)|(0<<0);              //源在系统总线上,地址增加   
    rDIDST2 = (U32)IISFIFO;                //DMA2初始目的地址   
    rDIDSTC2 = (0<<2)|(1<<1)|(1<<0);       //当TC为0时,中断发生,源在外围总线上,地址固定,一直为IISFIFO的0x55000010(小端)   
    if(result == 0){   
        flag = 0;   
        //握手模式,与APB时钟同步,当所有的传输结束,中断请求生成,单元传送,单服务模式,当传输计数器为0时,DMA通道关闭   
        rDCON2 = (1<<31)|(0<<30)|(1<<29)|(0<<28)|(0<<27)|(0<<24)|(1<<23)|(1<<22)|(1<<20)|(remain<<0);   
    }   
    else{   
        flag = 1;   
        rDCON2 = (1<<31)|(0<<30)|(1<<29)|(0<<28)|(0<<27)|(0<<24)|(1<<23)|(1<<22)|(1<<20)|(0xfffff<<0);   
    }   
    rDMASKTRIG2 = (0<<2)|(1<<1)|(0<<0);    //DMA通道开启   
    rIISCON |= 0x1;                        //IIS开启     
}     
void __irq DMA2_ISR(void){   
    rSRCPND |= 1<<19;   
    rINTPND |= 1<<19;   
    if(flag == 0){   
        rIISCON = 0x0;                  //关闭IIS               
        rIISFCON = 0x0;                 //关闭IISFIFO的DMA模式   
        rDMASKTRIG2 = 1<<2;             //关闭DMA   
    }   
    else{   
        result--;   
        rDISRC2 += 0x200000;            //因为是半字     
        if(result == 0){   
            flag = 0;   
            rDCON2 = (rDCON2 & ("0xfffff)) | (remain);   
        }   
        rDMASKTRIG2 = (0<<2)|(1<<1)|(0<<0);         
    }   
}   
int Main(){      
    rGPBUP  = rGPBUP  & "(0x7<<2) | (0x7<<2);   //The pull up function is disabled GPB[4:2] 1 1100         
    rGPBCON = rGPBCON & "(0x3f<<4) | (0x15<<4); //GPB[4:2]=Output(L3CLOCK):Output(L3DATA):Output(L3MODE)      
    rGPBDAT = 0x1ec;      
    rGPEUP  = rGPEUP  & "(0x1f)  | 0x1f;    //The pull up function is disabled GPE[4:0] 1 1111      
    rGPECON = rGPECON & "(0x3ff) | 0x2aa;   //GPE[4:0]=I2SSDO:I2SSDI:CDCLK:I2SSCLK:I2SLRCK      
    rMPLLCON = (150<<12)|(5<<4)|(0<<0);     
    rSRCPND |= 1<<19;   
    rINTPND |= 1<<19;   
    rINTMSK &= "(1<<19);  
    rGPFCON = 0xd57f;
    rGPFUP = 0x87;     
    pISR_DMA2 = (U32)DMA2_ISR;   
    PlayMusic(music, sizeof(music));      
    while(1){
            Led();                              //占用CPU
    }      
    return 0;      
}

作者:李万鹏
本文地址:https://www.eechina.com/thread-60216-1-1.html     【打印本页】

本站部分文章为转载或网友发布,目的在于传递和分享信息,并不代表本网赞同其观点和对其真实性负责;文章版权归原作者及原出处所有,如涉及作品内容、版权和其它问题,我们将根据著作权人的要求,第一时间更正或删除。
long361800 发表于 2011-4-4 09:11:42
你好,这个程序现在还没有调试出来,急啊。。。。可以把你的工程发一份到   long361800@163.com 吗??多谢了啊。。。。。
您需要登录后才可以发表评论 登录 | 立即注册

厂商推荐

相关视频

关于我们  -  服务条款  -  使用指南  -  站点地图  -  友情链接  -  联系我们
电子工程网 © 版权所有   京ICP备16069177号 | 京公网安备11010502021702
快速回复 返回顶部 返回列表