S3C2440 Mini 2440 DMA方式实现Uart(串口)通信

  搞了好久,终于完成了DMA方式实现串口通信。使用DMA不是很难,主要是DCONn的配置比较麻烦以及几种模式的理解。


DMA service mode:single service&Whole service。前一模式下,一次DMA请求完成一项原子操作,并且transfer count的值减1。后一模式下,一次DMA请求完成一批原子操作,直到transfer count等于0表示完成一次整体服务。具体对应DCON[27]。

 

DMA DREQ/DACK PROTOCOL:DMA请求和应答的协议有两种,Demond mode 和 Handshake mode。两者对Request和Ack的时序定义有所不同:

在Demond模式下,如果DMA完成一次请求后如果Request仍然有效,那么DMA就认为这是下一次DMA请求,并立即开始下一次的传输;

在Handshake模式下,DMA完成一次请求后等待Request信号无效,如果Request无效,DMA会无效ACK两个时钟周期,再等待下一次Request。


/***********************************************************************

功能:用DMA方式实现串口传输,
        将字符串数据通过DMA0通道传递给UTXH0,然后在终端
        显示。数据传输完后,DMA0产生中断,LED1亮。
************************************************************************
Mini2440 调试通过
2012-08-05      
*********************************************************************/
#include "2440addr.h"
#define MDIV 92
#define SDIV 1
#define PDIV 1
#define HDIVN 2
#define PDIVN 1
#define PCLK_  50000000
#define Led1_on() {rGPBDAT&=(~(1<<5)); }


char  *SendBuffer = "Hello world!" ;    //source data


/*****************LED 初始化************************************/
void Led_init()
{
    rGPBCON &=~((3<<10) | (3<<12) | (3<<14) | (3<<16)|(3<<0));
    rGPBCON |=((1<<10) | (1<<12) | (1<<14) | (1<<16)|(1<<0));
    rGPBUP &=~((1<<5) | (1<<6) | (1<<7) | (1<<8)|(1<<0));
    rGPBDAT =0xfffe;
}


/*****************UART0  io口初始化****************************/
void Uart0_io_init()      //uart io port
{
    rGPHCON =0xa0; //gph2,gph3 used for txd0,rxd0.
    rGPHUP=0x0;       //enable the pull up function 
}


/***************************UART0配置****************************/
void Uart0_init(int bandrate)
{
    rULCON0 |=0x3;                    //8-bit data ,1bit stop
    rUCON0  |=((1<<0) | (1<<3) | (2<<10) );   //used pclk as the clock,  transmit use DMA mode  ,  receive use  polling mode
    rUBRDIV0=(int)(PCLK_/(bandrate*16))-1 ;    //bandrate is 115200


}


/***************************时钟配置********************************************/
void Clk_init( )
{
    rCLKCON |=(1<<10);                                     //enable uart0 used pclk
    rLOCKTIME=0xffff;                                        //locktime
    rCLKCON |=(1<<13);                                      //gpio enable pclk                          
    rCLKDIVN =((PDIVN<<0) | (HDIVN<<1));    //1:4:8
    rMPLLCON |=((MDIV<<12) | (PDIV<<4) | (SDIV<<0));   // f_out=400MHZ
 //__asm{
                // mrc   p15, 0, r1, c1, c0, 0
               //  orr     r1, r1, #0xc0000000
                  //mcr p15, 0, r1, c1, c0, 0
        //   }
}


/*****************************DMA初始化***************************************/
void Dma_init()
{
    rGPBCON |=((1<<19)|(1<<21));              //GPB9,10 used for nXDACK0,nXDREQ0
    rDISRC0=(U32)SendBuffer;                    //source data address
    rDISRCC0 |=((0<<1)|(0<<0));                 //address increment , the source is in the AHB
    rDIDST0=(U32)UTXH0;                          //destination  is UTXH0
    rDIDSTC0 |=((0<<2)|(1<<1)|(1<<0));        //address not change ,  APB  ,   enable interrupt
   
  
    rDCON0 |=(1<<31)|(0<<30)|(1<<29)|(0<<28)|(0<<27)|(1<<24)|(1<<23)|(1<<22)|(0<<20)|(12);   
   //Handshake mode, PCLK synchronization ,enable dma interrupt , unit transfer ,  single service , 
   //UART0 is the request source, H/W request mode  ,disable auto reload ,  Byte transmit  ,12 Byte data
    rDMASKTRIG0=(0<<2)|(1<<1)|(0<<0);  //start dma transmit
}


/**********************DMA中断初始化***************************************/
void Dma_eint()
{
  rINTMSK &=~(1<<17);  //open the dma0 interrupt
}


/************************DMA中断服务函数*********************************/
void __irq Dma_isr()
{
    rSRCPND|=(1<<17);   //clear the srcpnd
    rINTPND |=(1<<17);   //clear the int pnd
    Led1_on();
}



int Main()
{     
      Clk_init();  
      Led_init();
      Uart0_io_init();
      Uart0_init(115200);
      Dma_eint();
      pISR_DMA0=(U32) Dma_isr;
      Dma_init();    
      while(1)
      {
       ;
      }  
      return 0;
}

你可能感兴趣的:(Mini2440裸机)