天天看點

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。

#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

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;

}

void Uart0_io_init()      //uart io port

{

    rGPHCON =0xa0; //gph2,gph3 used for txd0,rxd0.

    rGPHUP=0x0;       //enable the pull up function 

}

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

        //   }

}

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

}

void Dma_eint()

{

  rINTMSK &=~(1<<17);  //open the dma0 interrupt

}

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;

}

上一篇: S3C2440之UART