⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdi.c

📁 三星2443芯片
💻 C
📖 第 1 页 / 共 2 页
字号:
/*****************************************
  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 + -