📄 sdi.c
字号:
/*****************************************
NAME: SD/MMC.c
DESC: Normal SD/MMC test
HISTORY:
2006.12.18:GOM: draft ver 1.0
*****************************************/
#include "system.h"
#include "sdi.h"
#define INICLK 400000
#define SDCLK 25000000
#define MMCCLK 17500000
#define POL 0
#define INT 1
#define DMA 2
#define SDI_Tx_buffer (_NONCACHE_STARTADDRESS)
#define SDI_Rx_buffer (_NONCACHE_STARTADDRESS+(0x800000))
#define Card_OneBlockSize 512
int CMD13(void); // Send card status
int CMD9(void);
void __irq DMA_end(void);
// Global variables
unsigned int *Tx_buffer; //128[word]*16[blk]=8192[byte]
unsigned int *Rx_buffer; //128[word]*16[blk]=8192[byte]
volatile unsigned int rd_cnt;
volatile unsigned int wt_cnt;
volatile unsigned int BlockNum=0;
volatile unsigned int SD_MMC_Ins;
volatile unsigned int TR_end=0;
U32 Wide=0; // 0:1bit, 1:4bit
U32 MMC=0; // 0:SD , 1:MMC
int Maker_ID;
char Product_Name[7];
int Serial_Num;
volatile int RCA;
void * func_sdio_test[][2]=
{
(void *)SDIO_WriteTest, "SDIO Write ",
(void *)SDIO_ReadTest, "SDIO Read ",
(void *)SDIO_EraseBlock, "SDIO Block Erase ",
0,0
};
void Test_SDI(void)
{
int i;
RCA=0;
MMC=0;
SD_MMC_Ins=0;
SD_MMC_SETGPIO();
printf("\n[SDI test]\n");
if(!SD_card_init())
{
printf("\nCard initial fail\n");
}
if(!MMC)
printf("\n[SD card test...PCLK:%d,INICLK:%d,SDCLK:%d]\n",PCLK,INICLK,SDCLK);
else
printf("\n[MMC card test...PCLK:%d,INICLK:%d,MMCCLK:%d]\n",PCLK,INICLK,MMCCLK);
while(1)
{
i=0;
printf("\n\n");
while(1)
{ //display menu
printf("%2d:%s",i,func_sdio_test[i][1]);
i++;
if((int)(func_sdio_test[i][0])==0)
{
printf("\n");
break;
}
if((i%3)==0)
printf("\n");
}
printf("\nSelect (\"-1\" to exit) : ");
i = GetIntNum();
if(i==-1)
break; // return.
if( (i<((sizeof(func_sdio_test)-1)/8)) ) // select and execute...
( (void (*)(void)) (func_sdio_test[i][0]) )();
}
}
void SD_MMC_SETGPIO(void)
{
rGPECON = (rGPECON& ~(0x3ffc00))|(0x1<<21)|(0x1<<19)|(0x1<<17)|(0x1<<15)|(0x1<<13)|(0x1<<11);
}
void SDIO_ReadTest(void)
{
U32 i, j, StartAddr, OneBlockSize, Testmode;
U32 status,Addr_temp=0,transtime=0;
rd_cnt=0;
printf("\nSD/MMC block Read test\n");
printf("\nInput Read Start Address : ");
StartAddr = GetIntNum();
while((BlockNum == 0) || (BlockNum > 4096))
{
printf("Input Read Block Number[1~4096] : ");
BlockNum = GetIntNum();
}
OneBlockSize = Card_OneBlockSize;
Rx_buffer = (U32 *)SDI_Rx_buffer;
for(i=0 ; i<(OneBlockSize*BlockNum)/4 ; i++)
*(Rx_buffer+i) = 0x0;
rSDIDSTA = CRC_STAT_FAIL|RECEIVE_CRC_FAIL|DATA_TOUT|DATA_FINISH|BUSY_FINISH;
rSDIDCON = 0;
rSDIFSTA |= (1<<16); //FIFO reset
if(Wide==0)
rSDIDCON &= ~WIDE_BUS_EN;
else
rSDIDCON |= WIDE_BUS_EN;
rSDIDCON |=WORD_TRANSFER|RCV_AFTER_CMD|BLOCK_TRANSFER|BlockNum;
rSDIDCON |= DATA_RECEIVE_MODE|DATA_TRANSMIT_START;
printf("\n0:Polling read 1:Interrupt read 2:DMA read");
printf("\nSelect the test mode : ");
Testmode=GetIntNum();
switch(Testmode)
{
case POL:
if(BlockNum<2)
{
SDIO_Command((StartAddr*512), 17, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITHOUT_DATA);
while(Check_CMDend(17, 1) != 1)
SDIO_Command((StartAddr*512), 17, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITHOUT_DATA);
}
else
{
SDIO_Command((StartAddr*512), 18, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITHOUT_DATA);
while(Check_CMDend(18, 1) != 1)
SDIO_Command((StartAddr*512), 18, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITHOUT_DATA);
}
rSDICSTA = DATA_TIMEOUT|CMD_END|RESP_END; // Clear cmd_end(with rsp)
printf("\nTotal size =%x",OneBlockSize*BlockNum/4);
while(rd_cnt<(OneBlockSize*BlockNum)/4)
{
if(rSDIDSTA & DATA_TOUT) // Check timeout
{
printf("\nData status=%x",rSDICSTA);
rSDIDSTA |= DATA_TOUT; // Clear timeout flag
break;
}
status = rSDIFSTA; //If FIFO is not empty, receive data from Data Register(rSDIDAT0)
if(status& RX_FIFO_AVAILABLE_DETECT) // Is Rx data?
{
*Rx_buffer++ = rSDIDAT;
rd_cnt++;
}
}
printf("\nRead Count =%x",rd_cnt);
break;
case INT:
pISR_SDI_0=(unsigned)Rd_Int;
rINTMSK &= ~(BIT_SDI0);
rSDIIMSK=5; // Last & Rx FIFO half int.
if(BlockNum<2)
{
SDIO_Command((StartAddr*512), 17, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITHOUT_DATA);
while(Check_CMDend(17, 1) != 1)
SDIO_Command((StartAddr*512), 17, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITHOUT_DATA);
}
else
{
SDIO_Command((StartAddr*512), 18, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITHOUT_DATA);
while(Check_CMDend(18, 1) != 1)
SDIO_Command((StartAddr*512), 18, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITHOUT_DATA);
}
rSDICSTA = DATA_TIMEOUT|CMD_END|RESP_END; // Clear cmd_end(with rsp)
while(rd_cnt<128*BlockNum);
rINTMSK |= (BIT_SDI0);
rSDIIMSK=0; // All mask
break;
case DMA:
printf("\nDMA mode data write\n");
pISR_DMA=(unsigned)DMA_end;
rINTMSK&=~(BIT_DMA);
rINTSUBMSK&=~(BIT_SUB_DMA0);
rDISRC0 = (U32)(SDIDAT);
rDISRCC0 = (1<<1) | (1<<0);
rDIDST0 = (int)(Rx_buffer);
rDIDSTC0 = (0<<1)|(0<<0);
rDCON0 = (1<<31)|(0<<30)|(1<<29)|(1<<28)|(0<<27)|(1<<24)|(1<<22)|(2<<20) | (128*BlockNum)/4;
rDMASKTRIG0 = (0<<2)|(1<<1)|0; //no-stop, DMA0 channel on, no-sw trigger
rDMAREQSEL0 = (10 <<1) | 1;
StartStopwatch();
if(BlockNum<2)
{
SDIO_Command((StartAddr*512), 17, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITHOUT_DATA);
while(Check_CMDend(17, 1) != 1)
SDIO_Command((StartAddr*512), 17, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITHOUT_DATA);
}
else
{
SDIO_Command((StartAddr*512), 18, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITHOUT_DATA);
while(Check_CMDend(18, 1) != 1)
SDIO_Command((StartAddr*512), 18, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITHOUT_DATA);
}
rSDICSTA = DATA_TIMEOUT|CMD_END|RESP_END; // Clear cmd_end(with rsp)
rSDIDCON |=BURST4_EN|WORD_TRANSFER|TRANS_AFTER_RESP|BLOCK_TRANSFER|DMA_EN|BlockNum;
rSDIDCON |= DATA_RECEIVE_MODE|DATA_TRANSMIT_START;
if(Wide!=0)
rSDIDCON |= WIDE_BUS_EN;
else
rSDIDCON &= ~WIDE_BUS_EN;
while(!TR_end);
rINTMSK |= (BIT_DMA);
rINTSUBMSK |= (BIT_SUB_DMA0);
TR_end=0;
rDMASKTRIG0=(1<<2); //DMA0 stop
default : break;
}
if(!Check_DATend())
printf("\nData End Error....\n");
if(BlockNum>1)
{
SDIO_Command(0, 12, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITHOUT_DATA);
while(Check_CMDend(12, 1) != 1)
SDIO_Command(0, 12, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITHOUT_DATA);
rSDICSTA = CMD_END|RESP_END;; // Clear cmd_end(with rsp)
}
transtime = EndStopwatch();
CalculationBPS_NORMALSD_MMC(transtime);
Rx_buffer = (U32 *)SDI_Rx_buffer;
for(j=0 ; j<(OneBlockSize*BlockNum)/4 ; j++)
{
if(j%4 == 0)
printf("\n0x%04xh : ",Addr_temp);
printf("0x%08x ",*Rx_buffer++);
Addr_temp += 4;
}
BlockNum = 0;
printf("\n");
}
void SDIO_WriteTest(void)
{
U32 i, StartAddr, OneBlockSize, Offset, Testmode;
//U32 BlockNum=0;
U32 status;
U32 transtime;
wt_cnt=0;
printf("\nSD/MMC block write test\n");
printf("\n0:Polling write 1:Interrupt write 2:DMA write");
printf("\nSelect the test mode : ");
Testmode=GetIntNum();
printf("\nInput Write Start Address : ");
StartAddr = GetIntNum();
while((BlockNum == 0) || (BlockNum > 4096))
{
printf("Input Write Block Number[1~4095] : ");
BlockNum = GetIntNum();
}
printf("Input Write Data Offset : ");
Offset = GetIntNum();
OneBlockSize = Card_OneBlockSize;
Tx_buffer = (U32 *)SDI_Tx_buffer;
for(i=0 ; i<(OneBlockSize*BlockNum)/4 ; i++)
*(Tx_buffer+i) = (i+Offset);
rSDIFSTA |=(1<<16); //FIFO reset
rSDIDCON=(2<<22)|(1<<20)|(1<<17)|(Wide<<16)|(1<<14)|(3<<12)|(BlockNum<<0);
switch(Testmode)
{
case POL:
printf("\nPolling mode data write\n");
if(BlockNum<2)//single block
{
SDIO_Command((StartAddr*512), 24, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITHOUT_DATA);
while((Check_CMDend(24, 1) !=1))
SDIO_Command((StartAddr*512), 24, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITHOUT_DATA);
}
else//multi block
{
SDIO_Command((StartAddr*512), 25, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITHOUT_DATA);
while((Check_CMDend(25, 1) !=1))
SDIO_Command((StartAddr*512), 25, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITHOUT_DATA);
}
rSDICSTA = CMD_END|RESP_END; // Clear cmd_end(with rsp)
printf("\nBlock zise=%x\n",OneBlockSize*BlockNum/4);
while(wt_cnt < (OneBlockSize*BlockNum)/4)
{
status = rSDIFSTA;
if(status && TX_FIFO_AVAILABLE_DETECT)
{
rSDIDAT = *Tx_buffer++;
wt_cnt++;
}
}
printf("\nWrite count=%x\n",wt_cnt);
break;
case INT:
printf("\nInterrupt mode data write\n");
pISR_SDI_0=(unsigned)Wt_Int;
rINTMSK &= ~(BIT_SDI0);
rSDIIMSK=0x10; // Tx FIFO half int.
StartStopwatch();
if(BlockNum<2)//single block
{
SDIO_Command((StartAddr*512), 24, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITHOUT_DATA);
while((Check_CMDend(24, 1) !=1))
SDIO_Command((StartAddr*512), 24, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITHOUT_DATA);
}
else//multi block
{
SDIO_Command((StartAddr*512), 25, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITHOUT_DATA);
while((Check_CMDend(25, 1) !=1))
SDIO_Command((StartAddr*512), 25, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITHOUT_DATA);
}
rSDICSTA |= CMD_END|RESP_END; // Clear cmd_end(with rsp)
while(!TR_end);
rINTMSK |= (BIT_SDI0);
TR_end=0;
rSDIIMSK=0; // All mask
break;
case DMA:
printf("\nDMA mode data write\n");
pISR_DMA=(unsigned)DMA_end;
rINTMSK&=~(BIT_DMA);
rINTSUBMSK&=~(BIT_SUB_DMA0);
rDISRC0 = (int)(Tx_buffer);
rDISRCC0 = (0<<1) | (0<<0);
rDIDST0 = (U32)(SDIDAT);
rDIDSTC0 = (1<<1)|(1<<0);
rDCON0 = (1<<31)|(0<<30)|(1<<29)|(1<<28)|(0<<27)|(1<<24)|(1<<22)|(2<<20) |((128*BlockNum)/4);
rDMASKTRIG0 = (0<<2)|(1<<1)|0; //no-stop, DMA0 channel on, no-sw trigger
rDMAREQSEL0 = (10 <<1) | 1;
StartStopwatch();
if(BlockNum<2)//single block
{
SDIO_Command((StartAddr*512), 24, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITHOUT_DATA);
while((Check_CMDend(24, 1) !=1))
SDIO_Command((StartAddr*512), 24, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITHOUT_DATA);
}
else//multi block
{
SDIO_Command((StartAddr*512), 25, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITHOUT_DATA);
while((Check_CMDend(25, 1) !=1))
SDIO_Command((StartAddr*512), 25, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITHOUT_DATA);
}
rSDICSTA |= CMD_END|RESP_END; // Clear cmd_end(with rsp)
if(Wide!=0)
rSDIDCON |= WIDE_BUS_EN;
else
rSDIDCON &= ~WIDE_BUS_EN;
//printf("Origin TC=%x\n",(rDSTAT0&0xff));
rSDIDCON |=BURST4_EN|WORD_TRANSFER|TRANS_AFTER_RESP|BLOCK_TRANSFER|DMA_EN|BlockNum;
rSDIDCON |= DATA_TRANSMIT_MODE|DATA_TRANSMIT_START;
while(!TR_end);
rINTMSK |= (1<<20);
rINTSUBMSK |= (1<<27);
TR_end=0;
rDMASKTRIG0 |=(1<<2);//DMA Stop
default : break;
}
while(!Check_DATend()) ;
rSDIDCON=rSDIDCON&~(7<<12); //YH 040220, Clear Data Transfer mode => no operation, Cleata Data Transfer start
rSDIDSTA |= DATA_FINISH; // Clear data Tx/Rx end
if(BlockNum>1)
{
rSDIDCON=BUSY_AFTER_CMD|BLOCK_TRANSFER|WIDE_BUS_DIS|DATA_TRANSMIT_START|ONLYBUSY_CHECK|(BlockNum<<0);
SDIO_Command(0, 12, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITHOUT_DATA);
while(Check_CMDend(12, 1) != 1)
SDIO_Command(0, 12, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITHOUT_DATA);
rSDICSTA = CMD_END|RESP_END; // Clear cmd_end(with rsp)
if(!Check_BUSYend())
rSDIDSTA|= DATA_FINISH; //! Should be cleared by writing '1'.
}
transtime = EndStopwatch();
CalculationBPS_NORMALSD_MMC(transtime);
BlockNum =0;
}
void SDIO_EraseBlock(void)
{
U32 StartAddr, EndAddr;
printf("\nSD/MMC block erase test\n");
printf("\nInput Write Start Block Address(0x200, 0x400...) : "); //ex) 0x200[512bytes], 0x400, 0x800.....
StartAddr = GetIntNum();
printf("Input Write End Block Address(0x200, 0x400...) : "); //ex) 0x200[512bytes], 0x400, 0x800.......
EndAddr = GetIntNum();
if(MMC == 0)
{
SDIO_Command(StartAddr, 32, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITH_DATA);
while(Check_CMDend(32, 1) != 1)
SDIO_Command(StartAddr, 32, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITH_DATA);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -