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
}