【求助】SPI(DMA方式),代码分析!
[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); }
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")));}
SPI_DMA 8c050000 000A0000 RESERVED