www.pudn.com > s3c2443_test_code.zip > Hspi.c


/***************************************** 
  NAME: Hspi 
  DESC: High Speed SPI test 
  HISTORY: 
  2006.12.18:GOM: draft ver 1.0 
 *****************************************/ 
  
#include "system.h" 
#include "hspi.h" 
 
 
#define ECLK 		100*1000000 
 
//////////////////////////////////////////////////////////////////////////// 
 
#define BYTEOPERATION		1 
#define BURSTOPERATION		0 
#define Baudrate				8000000 
#define HSPI_CLK				HSPI_EPLL	 
volatile int DataCnt = 1024; 
 
/////////////////////////////////////////////////////////////////////////// 
 
volatile int TransferdDataCnt = 0; 
volatile int ReceivedDataCnt = 0; 
volatile char uMaxFifoSize = 64; 
 
#if BYTEOPERATION 
volatile unsigned char  *TxBufAddr, *RxBufAddr; 
#else 
volatile unsigned int  *TxBufAddr, *RxBufAddr; 
#endif 
 
volatile int BusTransWord; 
volatile int BusTransByte; 
volatile int PacketCntValue; 
 
volatile int SpiTxIntEnd=0; 
volatile int SpiRxIntEnd=0; 
volatile int SpiTxDmaEnd=0; 
volatile int SpiRxDmaEnd=0; 
 
#define TRAIL_CNT(n)        (((n)&0x3FF)<<19) 
#define RX_TRIG_LVL(n)      (((n)&0x3F)<<11) 
#define TX_TRIG_LVL(n)      (((n)&0x3F)<<5) 
#define PRESCALER(n)        (((n)&0xFF)<<0) 
 
#if 1//DMA Mode 
volatile int m_uTxTrigLvl = 0x14; 
volatile int m_uRxTrigLvl = 0x8; 
#else 
volatile int m_uTxTrigLvl = 0x4; 
volatile int m_uRxTrigLvl = 0x30; 
#endif 
 
#define SPI_TX_BUFFER	_NONCACHE_STARTADDRESS 
#define SPI_RX_BUFFER	(_NONCACHE_STARTADDRESS+0x200000) 
 
extern unsigned int ARMCLK, HCLK, PCLK; 
 
void * func_HSPI_test[][2]= 
{	 
	(void *)Test_Master_DMA_FullDuplex, 		"B2B Master DMA Full Duplex   ",	 
	(void *)Test_Slave_DMA_FullDuplex,		"B2B Slave DMA Full Duplex    ", 
	(void *)Test_MasterTxOnly_DMA,			"B2B Master Tx only by DMA    ", 
	(void *)Test_SlaveRxOnly_DMA,   			"B2B Slave Rx only by DMA     ", 
	(void *)Test_MasterRxOnly_DMA,			"B2B Master Rx only by DMA    ", 
	(void *)Test_SlaveTxOnly_DMA,   			"B2B Slave Tx only by DMA     ",	 
	 
	(void *)Test_Master_INT_FullDuplex, 		"B2B Master INT Full Duplex   ", 
	(void *)Test_Slave_INT_FullDuplex,  		"B2B Slave INT Full Duplex    ", 
	(void *)Test_MasterTxOnly_INT,			"B2B Master Tx only by INT    ", 
	(void *)Test_SlaveRxOnly_INT,			"B2B Slave Rx only by INT     ", 
	(void *)Test_MasterRxOnly_INT,			"B2B Master Rx only by INT    ", 
	(void *)Test_SlaveTxOnly_INT,   			"B2B Slave Tx only by INT     ",	 
 
	0,0 
}; 
 
void Test_HSPI(void) 
{   
	int i; 
 
	rSCLKCON |= (1<<14); 
	rPCLKCON |= (1<<6); 
 
	GPIOPortSet(); 
 
	rLOCKCON1=0x800;  
	rCLKSRC|=(1<<6);  // EPLL Output 
	SetEPLL(40, 1, 1);//96MHz 
	rEPLLCON &= ~(1<<24);  // EPLL ON  
	rCLKDIV1 = (rCLKDIV1 & ~(0x3<<24)) | (0x0<<24); 
	rMISCCR = rMISCCR & ~(0x7<<8) | (1<<8); 
	//rGPHCON = rGPHCON & ~(0x3<<28) | (1<<29); 
 
	//Uart_getc(); 
 
	while(1) 
	{ 
		i=0; 
		printf("\n\n"); 
		while(1) 
		{   //display menu 
	   		printf("%2d:%s",i,func_HSPI_test[i][1]); 
	    	i++; 
	    	if((int)(func_HSPI_test[i][0])==0) 
	    	{ 
				printf("\n"); 
				break; 
	    	} 
	    	if((i%2)==0) 
	    	printf("\n"); 
		} 
 
		printf("\nSelect (\"-1\" to exit) : "); 
		i = GetIntNum(); 
		if(i==-1)  
	   		break;		// return. 
		if( (i<((sizeof(func_HSPI_test)-1)/8)) )	// select and execute... 
	    	( (void (*)(void)) (func_HSPI_test[i][0]) )(); 
	} 
	 
} 
 
void Test_Master_DMA_FullDuplex(void) 
{ 
	U32 i; 
	U32 uTxBufAddr = _NONCACHE_STARTADDRESS; 
	U32 uRxBufAddr = (_NONCACHE_STARTADDRESS+0x200000); 
 
	BusTransWord = 1; 
	 
#if BYTEOPERATION 
	TxBufAddr = (U8 *)SPI_TX_BUFFER; 
	RxBufAddr = (U8 *)SPI_RX_BUFFER; 
#else 
	TxBufAddr = (U32 *)SPI_TX_BUFFER; 
	RxBufAddr = (U32 *)SPI_RX_BUFFER; 
#endif 
 
	// 0. Clear the Rx buffer. 
	for (i = 0; i>13)&0x7f); // check if Tx Fifo empty 
	while (!(rSPI_STATUS & STUS_TX_DONE)); // check if Tx done 
 
	nSSHigh(); 
 
	CompareData(uTxBufAddr, uRxBufAddr, DataCnt); 
 
 
	TransferdDataCnt = 0;	 
	ReceivedDataCnt=0; 
	SpiTxDmaEnd=0; 
	SpiRxDmaEnd=0; 
} 
 
void Test_Slave_DMA_FullDuplex(void) 
{ 
	U32 i; 
	U32 uTxBufAddr = _NONCACHE_STARTADDRESS; 
	U32 uRxBufAddr = (_NONCACHE_STARTADDRESS+0x200000); 
 
	BusTransWord = 1; 
	 
#if BYTEOPERATION 
	TxBufAddr = (U8 *)SPI_TX_BUFFER; 
	RxBufAddr = (U8 *)SPI_RX_BUFFER; 
#else 
	TxBufAddr = (U32 *)SPI_TX_BUFFER; 
	RxBufAddr = (U32 *)SPI_RX_BUFFER; 
#endif 
 
	// 0. Clear the Rx buffer. 
	for (i = 0; i>13)&0x7f); // check if Tx Fifo empty 
	while (!(rSPI_STATUS & STUS_TX_DONE)); // check if Tx done 
 
 
	CompareData(uTxBufAddr, uRxBufAddr, DataCnt); 
 
 
	TransferdDataCnt = 0; 
	ReceivedDataCnt=0; 
	SpiTxDmaEnd=0; 
	SpiRxDmaEnd=0; 
} 
 
 
 
void Test_MasterTxOnly_DMA(void) 
{ 
	U32 i; 
	U32 uTxBufAddr = _NONCACHE_STARTADDRESS; 
	//U32 uRxBufAddr = (_NONCACHE_STARTADDRESS+0x200000); 
 
	BusTransWord = 1; 
	 
#if BYTEOPERATION 
	TxBufAddr = (U8 *)SPI_TX_BUFFER; 
	RxBufAddr = (U8 *)SPI_RX_BUFFER; 
#else 
	TxBufAddr = (U32 *)SPI_TX_BUFFER; 
	RxBufAddr = (U32 *)SPI_RX_BUFFER; 
#endif 
 
	// 0. Clear the Rx buffer. 
	for (i = 0; i>6)&0x7f); // check if Tx Fifo empty 
	while (!(rSPI_STATUS & STUS_TX_DONE)); // check if Tx done 
 
	nSSHigh(); 
 
	printf("\nDMA transfer is done"); 
 
	rDISRC0 = 0; 
	rDISRCC0 = 0; 
	rDIDST0 = 0; 
	rDIDSTC0 = 0; 
	rDCON0 = 0; 
	rDMAREQSEL0 = 0; 
 
	TransferdDataCnt = 0; 
	ReceivedDataCnt=0; 
	SpiTxDmaEnd=0; 
	SpiRxDmaEnd=0; 
} 
 
 
void Test_SlaveRxOnly_DMA(void) 
{ 
	U32 i; 
	U32 uTxBufAddr = _NONCACHE_STARTADDRESS; 
	U32 uRxBufAddr = (_NONCACHE_STARTADDRESS+0x200000); 
 
	BusTransWord = 1; 
	 
#if BYTEOPERATION 
	TxBufAddr = (U8 *)SPI_TX_BUFFER; 
	RxBufAddr = (U8 *)SPI_RX_BUFFER; 
#else 
	TxBufAddr = (U32 *)SPI_TX_BUFFER; 
	RxBufAddr = (U32 *)SPI_RX_BUFFER; 
#endif 
 
	// 0. Clear the Rx buffer. 
	for (i = 0; i>6)&0x7f); // check if Tx Fifo empty 
 
	printf("\nTransfer Complete"); 
 
	TransferdDataCnt = 0; 
	ReceivedDataCnt=0; 
	SpiTxDmaEnd=0; 
	SpiRxDmaEnd=0; 
} 
 
void Test_Master_INT_FullDuplex(void) 
{ 
	U32 i; 
	U32 uTxBufAddr = _NONCACHE_STARTADDRESS; 
	U32 uRxBufAddr = (_NONCACHE_STARTADDRESS+0x200000); 
 
	SpiTxIntEnd = 0; 
	SpiRxIntEnd = 0; 
 
#if BYTEOPERATION 
	TxBufAddr = (U8 *)SPI_TX_BUFFER; 
	RxBufAddr = (U8 *)SPI_RX_BUFFER; 
#else 
	TxBufAddr = (U32 *)SPI_TX_BUFFER; 
	RxBufAddr = (U32 *)SPI_RX_BUFFER; 
#endif 
 
	pISR_SPI0 = (unsigned)HSPI_Int;	 
	 
	// 0. Clear the Rx buffer. 
	for (i = 0; i>13)&0x7f); // check if Rx Fifo empty 
	//while (!(rSPI_STATUS & STUS_TX_DONE)); // check if Tx done 
 
	nSSHigh(); 
	 
	CompareData(uTxBufAddr, uRxBufAddr, DataCnt); 
 
	TransferdDataCnt = 0; 
	ReceivedDataCnt=0; 
	SpiTxIntEnd=0; 
	SpiRxIntEnd=0; 
} 
 
 
void Test_Slave_INT_FullDuplex(void) 
{ 
	U32 i; 
	U32 uTxBufAddr = _NONCACHE_STARTADDRESS; 
	U32 uRxBufAddr = (_NONCACHE_STARTADDRESS+0x200000); 
 
	SpiTxIntEnd = 0; 
	SpiRxIntEnd = 0; 
	 
#if BYTEOPERATION 
	TxBufAddr = (U8 *)SPI_TX_BUFFER; 
	RxBufAddr = (U8 *)SPI_RX_BUFFER; 
#else 
	TxBufAddr = (U32 *)SPI_TX_BUFFER; 
	RxBufAddr = (U32 *)SPI_RX_BUFFER; 
#endif 
 
	pISR_SPI0 = (unsigned)HSPI_Int; 
	// 0. Clear the Rx buffer. 
	for (i = 0; i>13)&0x7f); // check if Rx Fifo empty 
	//while (!(rSPI_STATUS & STUS_TX_DONE)); // check if Tx done 
 
 
	CompareData(uTxBufAddr, uRxBufAddr, DataCnt); 
 
	TransferdDataCnt = 0; 
	ReceivedDataCnt=0; 
	SpiTxIntEnd=0; 
	SpiRxIntEnd=0; 
} 
 
void Test_MasterTxOnly_INT(void) 
{ 
	U32 i; 
	//U32 uTxBufAddr = _NONCACHE_STARTADDRESS; 
	//U32 uRxBufAddr = (_NONCACHE_STARTADDRESS+0x200000); 
 
	BusTransWord = 1; 
	 
#if BYTEOPERATION 
	TxBufAddr = (U8 *)SPI_TX_BUFFER; 
	RxBufAddr = (U8 *)SPI_RX_BUFFER; 
#else 
	TxBufAddr = (U32 *)SPI_TX_BUFFER; 
	RxBufAddr = (U32 *)SPI_RX_BUFFER; 
#endif 
 
	pISR_SPI0 = (unsigned)HSPI_Tx_Int; 
	// 0. Clear the Rx buffer. 
	for (i = 0; i>6)&0x7f); // check if Tx Fifo empty 
	while (!(rSPI_STATUS & STUS_TX_DONE)); // check if Tx done 
 
	nSSHigh(); 
	 
	printf("\nTransfer End\n"); 
 
	TransferdDataCnt = 0; 
	ReceivedDataCnt=0; 
	SpiTxIntEnd=0; 
	SpiRxIntEnd=0; 
} 
 
void Test_SlaveRxOnly_INT(void) 
{ 
	U32 i; 
	U32 uTxBufAddr = _NONCACHE_STARTADDRESS; 
	U32 uRxBufAddr = (_NONCACHE_STARTADDRESS+0x200000); 
 
	BusTransWord = 1; 
	 
#if BYTEOPERATION 
	TxBufAddr = (U8 *)SPI_TX_BUFFER; 
	RxBufAddr = (U8 *)SPI_RX_BUFFER; 
#else 
	TxBufAddr = (U32 *)SPI_TX_BUFFER; 
	RxBufAddr = (U32 *)SPI_RX_BUFFER; 
#endif 
 
	pISR_SPI0 = (unsigned)HSPI_Rx_Int; 
	// 0. Clear the Rx buffer. 
	for (i = 0; i>13)&0x7f); // check if Rx Fifo empty 
 
 
	CompareData(uTxBufAddr, uRxBufAddr, DataCnt); 
 
	TransferdDataCnt = 0; 
	ReceivedDataCnt=0; 
	SpiTxIntEnd=0; 
	SpiRxIntEnd=0; 
} 
 
void Test_MasterRxOnly_INT(void) 
{ 
	U32 i; 
	U32 uTxBufAddr = _NONCACHE_STARTADDRESS; 
	U32 uRxBufAddr = (_NONCACHE_STARTADDRESS+0x200000); 
 
	BusTransWord = 1; 
	 
#if BYTEOPERATION 
	TxBufAddr = (U8 *)SPI_TX_BUFFER; 
	RxBufAddr = (U8 *)SPI_RX_BUFFER; 
#else 
	TxBufAddr = (U32 *)SPI_TX_BUFFER; 
	RxBufAddr = (U32 *)SPI_RX_BUFFER; 
 
	m_uTxTrigLvl = 0x8; 
	m_uRxTrigLvl = 0x8; 
#endif 
 
	pISR_SPI0 = (unsigned)HSPI_Rx_Int; 
 
	// 0. Clear the Rx buffer. 
	for (i = 0; i>6)&0x7f); // check if Tx Fifo empty 
	while (!(rSPI_STATUS & STUS_TX_DONE)); // check if Tx done 
 
	printf("\nTransfer Complete"); 
 
	TransferdDataCnt = 0; 
	ReceivedDataCnt=0; 
	SpiTxIntEnd=0; 
	SpiRxIntEnd=0; 
} 
 
void HS_SPI_ERROR_CHECK(void) 
{ 
	printf("\nError check"); 
	pISR_SPI0 = (unsigned)HSPI_ERR_Int; 
	rSPI_INT_EN |= INT_TRAILING | INT_RX_OVERRUN | INT_RX_UNDERRUN | INT_TX_FIFORDY;	 
	rINTMSK &= ~(BIT_SPI0); 
} 
 
void InitHSPI(U32 MasterSlave, U32 Cpol, U32 Cpha, U32 ClkSel) 
{ 
	float uPrescaler = .0; 
 
	if(BYTEOPERATION == 1) 
		PacketCntValue = DataCnt; 
	else 
		PacketCntValue = DataCnt*4; 
 
	if (ClkSel == HSPI_PCLK) 
		uPrescaler = (float)(PCLK/2/Baudrate) - 1; 
	else if(ClkSel == HSPI_EPLL) 
		uPrescaler = (float)(ECLK/2/Baudrate) - 1; 
 
	printf("\nuPrescaler = %f",uPrescaler); 
 
	// 1. Set Tranfer Type 
	rCH_CFG = (rCH_CFG & ~(0x3f)) | 
		((MasterSlave == Master)? CH_MASTER : CH_SLAVE) | 
		((Cpol == CPOLHIGH)? CH_RISING : CH_FALLING) | 
		((Cpha == FORMAT_A)? CH_FORMAT_A : CH_FORMAT_B); 
 
	// 2. Clock Config 
	rCLK_CFG = (rCLK_CFG & ~(0x7ff)) | 
		((ClkSel == HSPI_PCLK)? CLK_CLKSEL_PCLK : CLK_CLKSEL_ECLK) | 
		((MasterSlave == Master)? CLK_ENCLK_ENABLE : CLK_ENCLK_DISABLE)| // SPI clk enable 
		PRESCALER((U8)uPrescaler); 
 
	// 3. Mode Config 
	rMODE_CFG = (rMODE_CFG & ~(0x1fffffff)) | 
		TRAIL_CNT(0x3ff) | 
		((BYTEOPERATION == 0)? MODE_BUS_SZ_WORD : MODE_BUS_SZ_BYTE) | 
		RX_TRIG_LVL(m_uRxTrigLvl) | 
		TX_TRIG_LVL(m_uTxTrigLvl) | 
		//(1<<4)| 
		((BURSTOPERATION == 1)? MODE_BUS_4BURST : MODE_BUS_SINGLE);	 
} 
 
void TxDMAInit(U32 uSrcAddr, U32 uDstAddr,U32 uDataCnt) 
{ 
	U32 uIsSrcApb = LOCAHB;  
	U32 uIsDstApb = LOCAPB; 
	U32 bSrcFixed = ADDRINC; 
	U32 bDstFixed = ADDRFIX; 
	U32 TC=0; 
	U32 eDataSz=0, Burst=0; 
 
	if(BYTEOPERATION == 1  && BURSTOPERATION == 1) 
		{ 
		eDataSz = HSPI_BYTE; 
		TC = uDataCnt/4; 
		} 
	else if(BYTEOPERATION == 1  && BURSTOPERATION == 0) 
		{ 
		eDataSz = HSPI_BYTE; 
		TC = uDataCnt; 
		} 
	else if(BYTEOPERATION == 0  && BURSTOPERATION == 1)  
		{ 
		eDataSz = HSPI_WORD; 
		TC = uDataCnt/4; 
		} 
	else if(BYTEOPERATION == 0  && BURSTOPERATION == 0)  
		{ 
		eDataSz = HSPI_WORD; 
		TC = uDataCnt; 
		} 
	Burst = BURSTOPERATION; 
 
	printf("\nTC = %x",TC); 
	 
	rDISRC0 = uSrcAddr; 
	rDISRCC0 =  uIsSrcApb<<1 | bSrcFixed<<0; 
	rDIDST0 = uDstAddr; 
	rDIDSTC0 = uIsDstApb<<1 | bDstFixed<<0; 
	rDCON0 = (rDCON0 & ~(0xffffffff)) |(U32)( (1<<31) |(1<<29) |(Burst<<28) |(0<<27)|(1<<24) |(1<<22) |(eDataSz<<20) |(TC)); 
	rDMAREQSEL0 = (0 <<1) | 1; 
} 
 
void RxDMAInit(U32 uSrcAddr, U32 uDstAddr, U32 uDataCnt) 
{ 
	U32 uIsSrcApb = LOCAPB;  
	U32 uIsDstApb = LOCAHB; 
	U32 bSrcFixed = ADDRFIX; 
	U32 bDstFixed = ADDRINC; 
	U32 TC=0; 
	U32 eDataSz=0, Burst=0; 
 
	if(BYTEOPERATION == 1  && BURSTOPERATION == 1) 
		{ 
		eDataSz = HSPI_BYTE; 
		TC = uDataCnt/4; 
		} 
	else if(BYTEOPERATION == 1  && BURSTOPERATION == 0) 
		{ 
		eDataSz = HSPI_BYTE; 
		TC = uDataCnt; 
		} 
	else if(BYTEOPERATION == 0  && BURSTOPERATION == 1)  
		{ 
		eDataSz = HSPI_WORD; 
		TC = uDataCnt/4; 
		} 
	else if(BYTEOPERATION == 0  && BURSTOPERATION == 0)  
		{ 
		eDataSz = HSPI_WORD; 
		TC = uDataCnt; 
		} 
	Burst = BURSTOPERATION; 
	 
	printf("\nTC = %x",TC); 
	 
	rDISRC1 = uSrcAddr; 
	rDISRCC1 =  uIsSrcApb<<1 | bSrcFixed<<0; 
	rDIDST1 = uDstAddr; 
	rDIDSTC1 = uIsDstApb<<1 | bDstFixed<<0; 
	rDCON1 = (rDCON1 & ~(0xffffffff)) | (U32)((1<<31) |(1<<29) |(Burst<<28) |(0<<27) |(1<<24) |(1<<22) |(eDataSz<<20) |(TC));  
	rDMAREQSEL1 = (1 <<1) | 1; 
} 
 
void __irq HSPI_Tx_Int(void) 
{ 
	U32 i=0; 
	U32 x,TxTriglevel =0; 
	 
	rINTMSK |= (BIT_SPI0); 
	ClearPending(BIT_SPI0); 
	rPENDING_CLR |= (1<<4) | (1<<3) | (1<<2) | (1<<1); 
 
	#if BYTEOPERATION 
		x = ((rSPI_STATUS>>6)&0x7f); 
		TxTriglevel = 64 -x; 
	#else 
		x = ((rSPI_STATUS>>6)&0x7f)/4; 
		TxTriglevel = 16-x; 
	#endif 
	 
	while (i>13)&0x7f); 
	#else 
		RxTriglevel = ((rSPI_STATUS>>13)&0x7f)/4; 
	#endif 
	 
	//printf("\nRxTriglevel = %x",(rSPI_STATUS>>13)&0x7f); 
	while (i>13)&0x7f); 
				} 
			else 
				RxReadCnt = ((rSPI_STATUS>>13)&0x7f)/4;			 
			 
			while (i>6)&0x7f); 
				TxWriteCnt = 64 -x; 
				} 
			else 
				{ 
				x = ((rSPI_STATUS>>6)&0x7f)/4; 
				TxWriteCnt = 16-x; 
				} 
			 
			while (i %08x=%02x", pD0, *pD0, pD1, *pD1); 
			ErrCnt++; 
		} 
		pD0++; 
		pD1++; 
	} 
	printf("\nTotal Error cnt = %d",ErrCnt); 
 
	if(ErrCnt == 0) 
		printf("\nData Compare Ok\n"); 
} 
 
void CompareDataByte(U8 a0, U8 a1, U8 bytes) 
{ 
	U8 * pD0 = (U8 *)a0; 
	U8 * pD1 = (U8 *)a1; 
	U8  ErrCnt = 0; 
	U32 i; 
 
	for (i=0; i %08x=%02x", pD0, *pD0, pD1, *pD1); 
			ErrCnt++; 
		} 
		pD0++; 
		pD1++; 
	} 
	printf("\nTotal Error cnt = %d",ErrCnt); 
 
	if(ErrCnt == 0) 
		printf("\nData Compare Ok\n"); 
} 
 
void Reset(void) 
{ 
	rCH_CFG |= (1<<5); 
	printf("\nHS SPI reset\n"); 
	rCH_CFG &= ~(1<<5); 
} 
 
void nSSLow(void) 
{ 
	rSLAVE_SEL = 0; 
} 
 
void nSSHigh(void) 
{ 
	rSLAVE_SEL = 1; 
} 
 
void GPIOPortSet(void) 
{ 
	rMISCCR |= (U32)(1<<31); 
	rGPECON = rGPECON & ~(0x3f<<22) | (1<<27) | (1<<25) | (1<<23); // SPICLK0, SPIMOSI0, SPIMISO0 
	rGPLCON = rGPLCON & ~(0x3ff<<20) | (1<<29) | (1<<27) | (1<<25) | (1<<23) | (1<<21); // SS1, SS0, SPIMISO1, SPIMOSI1, SPICLK1 
}