当前位置: 代码迷 >> WinCE >> SPI(DMA方式),代码分析
  详细解决方案

SPI(DMA方式),代码分析

热度:113   发布时间:2016-04-28 13:10:41.0
【求助】SPI(DMA方式),代码分析!
[code=C/C++][/code]
C/C++ code
void SPI_Init(){    //----------- IMPORTANT: By default, the internal clock is disabled.  To configure the controller ------    //                          we must first enable it.             StartSPIClock();              // ----------------------Configure the GPIO pins for SPI mode -------------------------------    //    //           nSPICS0  (chip select)        = GPG2    //           SPICLK0  (SPI clock)            = GPE13    //           SPIMOSI0 (SPI output data)    = GPE12    //           SPIMISO0 (SPI input data)        = GPE11           s2440IOP->rGPGCON &=~(0x3<<4);     s2440IOP->rGPGCON |=(0x1<<4);  //GPG2 [OUTPUT]     s2440IOP->rGPGUP &=~(0x1<<2);  //enable pullup            s2440IOP->rGPECON &= ~((3<<26) | (3<<24)|(3<<22));   s2440IOP->rGPECON |= ((0x2<<26)|(0x2<<24)|(0x2<<22));   s2440IOP->rGPEUP |= (0x7<<11);   //SPI register init    s2440SPIreg->rSPCON0=(0<<5)| //(SMOD) ; 10 = DMA mode ;  01 = interrupt mode                                                        (1<<4)|   //clock enable                                                (1<<3)|   //(MSTR) :1 = master mode                                                (SPI_CLOCK_POLARITY<<2)|    //(CPOL) Determine an active high or active low clock;                                                 (1<<1)|     //(CPHA)   format B                                                (0);        //TAGD          s2440SPIreg->rSPPIN0=(0<<2)|(1<<1)|(0);                     // RETAILMSG(DEBUG_ZONE,(TEXT("SPI_Init__rSPSTA0={0x%x}\r\n"),s2440SPIreg->rSPSTA0));        SetSPIClockRate(CLK_RATE_SIXTY4);          }



C/C++ code
void DmaWriteData(/*const unsigned char *buffer,*/DWORD dwNumBytes){   RETAILMSG(1,(TEXT(">>>>DmaWriteData \r\n")));      RETAILMSG(DEBUG_ZONE,(TEXT("dwNumBytes=%d\r\n"),dwNumBytes));       unsigned int ct=0;   int delay_count=0,i=0,waitCount=0;        for(ct=0;ct<(dwNumBytes);ct+=2)   RETAILMSG(DEBUG_ZONE,(TEXT("%dth:{0x%x,0x%x}\r\n"),ct/2 ,*(pDmaBuffer+ct),*(pDmaBuffer+ct+1)));       RETAILMSG(DEBUG_ZONE,(TEXT("DMA__Current source address before tx ={0x%x}\r\n"),s2440DMA->rDCSRC1));       //------------------------------ wait for DMA to complete.-------------------------------    while((s2440DMA->rDSTAT1 & 0xfffff)!=0)    {        RETAILMSG(1,(TEXT("DMA is busy now! 1th\r\n")));    };        if((s2440DMA->rDSTAT1 & 0x300000)==0)    {         RETAILMSG(1,(TEXT("DMA is ready now! 1th\r\n")));    }//-------------------------------- Configure the DMA SPI mode -------------------------    SpiInitDma();                  //nss0    low        s2440IOP->rGPGCON &=~(0x3<<4);     s2440IOP->rGPGCON |=(0x3<<4);       //s2440IOP->rGPGUP &=~(0x1<<2);  //enable pullup          s2440IOP->rGPGDAT &=~(1<<2);          SPI_CS_High();    SPI_CS_Low();           s2440DMA->rDISRC1 =(int)(SPI_BUF_PHYS_BASE);   //源地址 :DMA对应物理地址    s2440DMA->rDISRCC1 &= ~(0x3);   // Source is system bus(内存块中), increment addr(每次数据传送之后地址递增)     //---------------- Initialize the DMA channel to send data over the SPI bus --------------------    s2440DMA->rDIDST1    = (int)D_ADDR;      // 要传送的目的地址,这里应该是SPI的数据数据地址(SPTDAT0)       s2440DMA->rDIDSTC1 = //(CHK_INT<<2)|    //中断触发模式                                                     (1<<1)|   //                                                     (1);    // fixed addr ,                                                       //-------- Configure the DMA channel's transfer characteristics: handshake, sync PCLK,  ----------    //           single tx, single service,  no auto-reload, byte, tx count        s2440DMA->rDCON1    = (1<<31)|  //Handshake mode   ,                                                (0<<30) |  //while for those attached to APB system, it should be set to 0                                                //(1<<30) |  //while for those attached to APB system, it should be set to 0                                                (0<<29) |  // 决定DMA中断何时产生(i.e.CURR_TC becomes 0).                                                (0<<28) |  // a unit transfer is performed. 数据一直传送直到TC为0                                                (1<<27) |  //Whole service mode #if HARD_TRIGGER                                                (0x3<<24) |   //DMA request source is  SPI                                                (1<<23) |     //H/W request mode#else                                                    (0<<23) |  //S/W request mode ,triggered by setting SW_TRIG #endif                                                (1<<22) |   //NO_DMA_AUTO_RELOAD                                                (0<<20) |  //Data size to be transferred.   ;BYTE                                                (dwNumBytes)  ;  //                 RETAILMSG(1, (TEXT(" 1TH CURR_TC =%x.\r\n"),s2440DMA->rDSTAT1));                                          //------------------------------ wait for DMA to complete.-------------------------------    while((s2440DMA->rDSTAT1 & 0xfffff)!=0)    {         RETAILMSG(1, (TEXT(" ... CURR_TC =%x.\r\n"),s2440DMA->rDSTAT1));       RETAILMSG(1,(TEXT("DMA is busy now! 2th\r\n")));    };        //RETAILMSG(1, (TEXT("  CURR_TC =%d.\r\n"),s2440DMA->rDSTAT1));    //---------------------------------Trigger DMA---------------------------------------  //Note. This bit should not be changed manually during DMA operations     s2440DMA->rDMASKTRIG1 &= ~(1<<2);//    s2440DMA->rDMASKTRIG1 |= (1<<1);  //0110    s2440DMA->rDMASKTRIG1 = 0x006;  //0110            while((s2440DMA->rDSTAT1 & 0xfffff)!=0)    {         RETAILMSG(1, (TEXT(" DMA_CURR_TC =%x.\r\n"),s2440DMA->rDSTAT1));     };#if 1    RETAILMSG(DEBUG_ZONE,(TEXT("DMA__rDSTAT1.={0x%x}\r\n"),s2440DMA->rDSTAT1));//[21:20] 0:ready,1:busy   [19:0] Current value of transfer count    RETAILMSG(DEBUG_ZONE,(TEXT("SPI__rSPTDAT0={0x%x}\r\n"),s2440SPIreg->rSPTDAT0));//输出为0x8,说明数据是传递到SPTDAT端了            RETAILMSG(DEBUG_ZONE,(TEXT("SPI__rSPSTA0={0x%x}\r\n"),s2440SPIreg->rSPSTA0));    //[0] 0 = not ready ;1 = data Tx/Rx ready;//[1] 0 = not detect 1 = multi master error detect//[2] This flag is set if the SPTDATn is written or SPRDATn is read whilea transfer is in progress and cleared by reading the SPSTAn.   0 = not detect 1 = collision error detect    RETAILMSG(DEBUG_ZONE,(TEXT("DMA__Current source address ={0x%x}\r\n"),s2440DMA->rDCSRC1));    RETAILMSG(DEBUG_ZONE,(TEXT("DMA__Current destination address={0x%x}\r\n"),s2440DMA->rDCDST1));#endif           delay_count = 0;        while((s2440DMA->rDSTAT1 & 0xfffff)==0)    {            if( delay_count++ > DELAY_COUNT )        {                    RETAILMSG(1, (TEXT("  timeout occurred while waiting to start DMA.\r\n")));            break;            }        }      SPI_CS_High();       RETAILMSG(1,(TEXT("<<<<<<DmaWriteData \r\n")));}
  相关解决方案