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

📄 hs_mmc.c

📁 Samsung S3C2443 Test program source code
💻 C
📖 第 1 页 / 共 3 页
字号:
#include <stdio.h>
#include <string.h>
#include "def.h"
#include "option.h"
#include "2443addr.h"
#include "system.h"
#include "pll.h"
#include "console.h"
#include "hs_mmc.h"

#define POL_Ver1		0
#define INT_Ver1		1
#define DMA_Ver1	2
#define SDI_Tx_buffer_HSMMC (_NONCACHE_STARTADDRESS)
#define SDI_Rx_buffer_HSMMC (_NONCACHE_STARTADDRESS+(0x300000))
#define SDI_Compare_buffer_HSMMC (_NONCACHE_STARTADDRESS+(0x600000))


#define Card_OneBlockSize_ver1 512

// Global variables
unsigned int *Tx_buffer_HSMMC;	
unsigned int *Rx_buffer_HSMMC;
unsigned int *Compare_buffer_HSMMC;

volatile unsigned int rd_cnt_HSMMC;
volatile unsigned int wt_cnt_HSMMC;
volatile unsigned int BlockNum_HSMMC=0;

volatile unsigned int WriteBlockCnt_INT=0;
volatile unsigned int ReadBlockCnt_INT=0;
volatile unsigned int WRITEINT_DONE=0;
volatile unsigned int READINT_DONE=0;
volatile unsigned int COMPARE_INT_DONE=0;
volatile unsigned int CompareCnt_INT=0;
volatile unsigned int BufferBoundary_INT_Cnt=0;

volatile unsigned int HS_DMA_END = 0;
volatile unsigned int HS_CARD_DETECT = 0;

volatile int OCRcheck=0;
volatile int ThisIsMmc=0;
volatile int m_uRca=0;
volatile int m_ucMMCSpecVer = 0;
volatile int SDSpecVer;

extern	unsigned int ARMCLK, HCLK, PCLK;

//////////////////////////////////////////////////////////////////////////

#define NEW_SD_CARD		1
#define BUFFER_BOUNDARY	0
#define HCLK_OPERATION		0

//////////////////////////////////////////////////////////////////////////

void * func_HSMMC_test[][2]=
{	
    (void *)HS_MMC_WriteTest,       	    "SDIO Write          ",
    (void *)HS_MMC_ReadTest,           	"SDIO Read           ",
    (void *)HS_MMC_EraseBlock,            "SDIO Block Erase    ",
    0,0
};

void Test_HS_MMC(void)
{  
	int i;

	HS_MMC_SETGPIO();	

	//HS_MMC_CardDetect();	

	HS_MMC_Reset();	
	
	if(!HS_MMC_init())
	{
		printf("\nCard initial fail\n");
	}

	while(1)
	{
		i=0;
		printf("\n\n");
		while(1)
		{   //display menu
	   		printf("%2d:%s",i,func_HSMMC_test[i][1]);
	    	i++;
	    	if((int)(func_HSMMC_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_HSMMC_test)-1)/8)) )	// select and execute...
	    	( (void (*)(void)) (func_HSMMC_test[i][0]) )();
	}
	
}


int HS_MMC_init(void)
{
	int i, Card_State, blocksize,BD_BUS_WIDTH,ucBusWidth;
	char key;

	ClockOnOff(0);
	rSCLKCON |=(1<<13);

	//SetClock(SD_HCLK, 0x80);
	SetClock(SD_EXTCLK, 0x20);
	
	rHM_TIMEOUTCON = 0xe;

	HostCtrlSpeedMode(NORMAL);

	InterruptEnable(0xff, 0xff);

	printf("rHM_NORINTSTS = %x\n",rHM_NORINTSTS);
	
	IssueCommand(0,0x00,0);//Idle State
	printf("\nEnter to the Idle State\n");

	OCRcheck =1;

	if(SetMMCOCR())
	{
		ThisIsMmc=1;
		printf("MMC card is detected\n");
	}
	else if(SetSDOCR())
	{
		ThisIsMmc=0;
		printf("SD card is detected\n");
	}
	else
		return 0;

	OCRcheck =0;
	
	// Check the attached card and place the card in the IDENT state rHM_RSPREG0
	IssueCommand(2,0,0);	
	printf("\n - Product Name : %c%c%c%c%c%c\n",((rHM_RSPREG2>>24)&0xFF),((rHM_RSPREG2>>16)&0xFF),((rHM_RSPREG2>>8)&0xFF),(rHM_RSPREG2&0xFF),((rHM_RSPREG1>>24)&0xFF),((rHM_RSPREG1>>16)&0xFF));		

	// Send RCA(Relative Card Address). It places the card in the STBY state
	m_uRca = (ThisIsMmc) ? 0x0001 : 0x0000;
 	IssueCommand(3,m_uRca,0);	
	
	if(!ThisIsMmc)
 		{
			m_uRca = (rHM_RSPREG0>>16)&0xFFFF;			
			printf("=>  RCA=0x%x\n", m_uRca);			
 		}	
	
	printf("\nEnter to the Stand-by State\n");
	
	IssueCommand(9, m_uRca, 0);//Send CSD
	
	DisplayCardInformation();

	IssueCommand(7, m_uRca, 0);	
	//printf("\nEnter to the Transfer State\n");		
		
//////////////////////// Operating Clock setting ////////////////////////////
#if HCLK_OPERATION
	ClockConfig(SD_HCLK, 1);// Divisor 1 = Base clk /2	,Divisor 2 = Base clk /4, Divisor 4 = Base clk /8 ...		
#else
	rLOCKCON1=0x800; 
	rCLKSRC|=(1<<6);  // EPLL Output
	//SetEPLL(42, 1, 1);//100MHz
	SetEPLL(40, 1, 1);//96MHz
	rEPLLCON &= ~(1<<24);  // EPLL ON 
	rCLKDIV1 = (rCLKDIV1 & ~(0x3<<6)) | (0x0<<6);
	rMISCCR = rMISCCR & ~(0x7<<8) | (1<<8);
	rGPHCON = rGPHCON & ~(0x3<<28) | (1<<29);
	ClockConfig(SD_EPLL, 1);// Divisor 1 = Base clk /2 ,Divisor 2 = Base clk /4, Divisor 4 = Base clk /8 ...	
	//ClockConfig(SD_EPLL, 2);// Divisor 1 = Base clk /2	,Divisor 2 = Base clk /4, Divisor 4 = Base clk /8 ...

/*
	rSCLKCON |=(1<<13);
	SetClock(SD_EXTCLK, 0);// HCLK = 100MHz, SD CLK = 390KHz
	ClockOnOff(0); // when change the sd clock frequency, need to stop sd clock.
*/
#endif
///////////////////////////////////////////////////////////////////////
	while (!SetDataTransferWidth());	

	while (!IsCardInProgrammingState());

	printf("\nSet a One Block size\n");
	while(!IssueCommand(16, 512, 0));//Set the One Block size	

	rHM_NORINTSTS = 0xffff;
}


void HS_MMC_WriteTest(void)
{
	U32 i, j, StartAddr,  OneBlockSize, Offset, Testmode;
	U32 TotalWriteByte, WriteBlockCnt =0;
	U32 transtime;

	U32 uTxBufAddr = SDI_Tx_buffer_HSMMC;
	U32 uCompareBufAddr = SDI_Compare_buffer_HSMMC;
	
	wt_cnt_HSMMC=0;
	BlockNum_HSMMC = 0;
	wt_cnt_HSMMC = 0;
	WriteBlockCnt_INT = 0;
	HS_DMA_END = 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 block number : ");
	StartAddr = GetIntNum();

	printf("Input Write Data Offset : ");
	Offset = GetIntNum();

	while((BlockNum_HSMMC == 0) || (BlockNum_HSMMC > 65535))
	{
		printf("Input number of Block [1~65535] : ");
		BlockNum_HSMMC = GetIntNum();
	}

	OneBlockSize = Card_OneBlockSize_ver1;
	
	Tx_buffer_HSMMC = (U32 *)SDI_Tx_buffer_HSMMC;
    	for(i=0 ; i<(OneBlockSize*BlockNum_HSMMC)/4 ; i++)
    		{
    		*(Tx_buffer_HSMMC+i) = (i+Offset);   	
   		}				
	
	switch(Testmode)
		{
			case  POL_Ver1:
				printf("\nPolling mode data write\n");

				SetBlockSizeReg(7, 512); // Maximum DMA Buffer Size, Block Size
				SetBlockCountReg(BlockNum_HSMMC); // Block Numbers to Write
				SetArgumentReg(StartAddr*512); // Card Address to Write

				if(BlockNum_HSMMC == 1)//single block
					{
						SetTransferModeReg(0, 0, 1, 1, 0);
						SetCommandReg(24, 0); 	
					}
				else//multi block
					{
						SetTransferModeReg(1, 0, 1, 1, 0);
						SetCommandReg(25, 0); 
					}

				if (!WaitForCommandComplete())
					{
						printf("\nCommand is NOT completed\n");
					}
				ClearCommandCompleteStatus();

				for(j=0; j<BlockNum_HSMMC; j++)
					{
						if (!WaitForBufferWriteReady())
							printf("WriteBuffer NOT Ready\n");
						else
							ClearBufferWriteReadyStatus();

						for(i=0; i<512/4; i++)//512 byte should be writed.
							{
								rHM_BDATA = *Tx_buffer_HSMMC++;	
				  		 		wt_cnt_HSMMC++;						
							}
						WriteBlockCnt ++;
						//printf("\nWrite block count = %d", WriteBlockCnt);
					}

				TotalWriteByte = wt_cnt_HSMMC *4;
				printf("\nWrite count=%dByte\n",TotalWriteByte);
				if(!WaitForTransferComplete())
					{
					printf(("Transfer is NOT Complete\n"));
					}
				ClearTransferCompleteStatus();
				
				break;

			case INT_Ver1:

				printf("\Interrupt mode data write\n");
				pISR_SDI_1=(unsigned)HS_WRITE_INT;
				
				SetBlockSizeReg(7, 512); // Maximum DMA Buffer Size, Block Size
				SetBlockCountReg(BlockNum_HSMMC); // Block Numbers to Write
				SetArgumentReg(StartAddr*512); // Card Address to Write

				StartStopwatch();
				
				if(BlockNum_HSMMC == 1)//single block
					{
						SetTransferModeReg(0, 0, 1, 1, 0);
						SetCommandReg(24, 0); 	
					}
				else//multi block
					{
						SetTransferModeReg(1, 0, 1, 1, 0);
						SetCommandReg(25, 0); 
					}

				if (!WaitForCommandComplete())
					{
						printf("\nCommand is NOT completed\n");
					}
				ClearCommandCompleteStatus();

				printf("\nInterupt mode Write Start\n");
				rINTMSK &= ~(BIT_SDI1);
				rHM_NORINTSIGEN = rHM_NORINTSIGEN & ~(0xffff) | BUFFER_WRITEREADY_SIG_INT_EN;	

				while(!WRITEINT_DONE);

				//printf("\nInterupt mode Write End\n");
				
				if(!WaitForTransferComplete())
					{
					printf(("Transfer is NOT Complete\n"));
					}
				ClearTransferCompleteStatus();
				

				transtime = EndStopwatch();
				CalculationBPS_HSMMC(transtime);
				
	    			break;
					
			case DMA_Ver1:

				#if BUFFER_BOUNDARY
				
				pISR_SDI_1 = (unsigned)HS_DMA_INT;
				rINTMSK &= ~(BIT_SDI1);				
				rHM_NORINTSTSEN |= (DMA_STS_INT_EN |TRANSFERCOMPLETE_STS_INT_EN);
				rHM_NORINTSIGEN = rHM_NORINTSIGEN & ~(0xffff) | DMA_SIG_INT_EN |TRANSFERCOMPLETE_SIG_INT_EN;
				
				SetSystemAddressReg(SDI_Tx_buffer_HSMMC);// AHB System Address For Write
				SetBlockSizeReg(0, 512); // 4K Byte Buffer Boundary, Block Size				
				SetBlockCountReg(BlockNum_HSMMC); // Block Numbers to Write	
				SetArgumentReg(StartAddr*512);// Card Start Block Address to Write				

				#else		

				pISR_SDI_1 = (unsigned)HS_DMA_INT;
				
				rINTMSK &= ~(BIT_SDI1);				
				//rHM_NORINTSTSEN &= ~(DMA_STS_INT_EN|BLOCKGAP_EVENT_STS_INT_EN);
				rHM_NORINTSTSEN = (rHM_NORINTSTSEN & ~(0xffff)) |
									BUFFER_READREADY_STS_INT_EN | 
									BUFFER_WRITEREADY_STS_INT_EN |
									TRANSFERCOMPLETE_STS_INT_EN |
									COMMANDCOMPLETE_STS_INT_EN;
				rHM_NORINTSIGEN = (rHM_NORINTSIGEN & ~(0xffff)) | TRANSFERCOMPLETE_SIG_INT_EN;				
			
				SetSystemAddressReg(SDI_Tx_buffer_HSMMC);// AHB System Address For Write
				SetBlockSizeReg(7, 512); // Maximum DMA Buffer Size, Block Size				
				SetBlockCountReg(BlockNum_HSMMC); // Block Numbers to Write	
				SetArgumentReg(StartAddr*512);// Card Start Block Address to Write				
				
				#endif			

				//StartStopwatch();

				if (BlockNum_HSMMC == 1)
				{
					SetTransferModeReg(0, 0, 1, 1, 1);
					SetCommandReg(24, 0); // CMD25: Single-Write
				}
				else
				{	// (u32 MultiBlk, u32 DataDirection, u32 AutoCmd12En, u32 BlockCntEn, u32 DmaEn)
					SetTransferModeReg(1, 0, 1, 1, 1);
					SetCommandReg(25, 0); // CMD25: Multi-Write
				}
				
				if (!WaitForCommandComplete())
				{
					printf("\nCommand is NOT completed\n");
				}
				ClearCommandCompleteStatus();		
				
				while(!HS_DMA_END);

				if(!WaitForTransferComplete())
					{
					printf(("Transfer is NOT Complete\n"));
					}
				ClearTransferCompleteStatus();
				
				rHM_NORINTSTS |= (1<<3);
				
				//transtime = EndStopwatch();
				//CalculationBPS_HSMMC(transtime);
				
				printf(("\nDMA Write End\n"));
				
				break;	
				
			default :
				break;					
		}	

	DataRead_ForCompare(StartAddr);
	DataCompare_HSMMC(uTxBufAddr, uCompareBufAddr, BlockNum_HSMMC * 128);
	
	BlockNum_HSMMC = 0;
	wt_cnt_HSMMC = 0;
	WriteBlockCnt_INT = 0;
	HS_DMA_END = 0;
	BufferBoundary_INT_Cnt = 0;

	CompareCnt_INT = 0;
	Compare_buffer_HSMMC = 0;
}


void HS_MMC_ReadTest(void)
{
	U32 i, j, StartAddr,  OneBlockSize, Offset, Testmode, Addr_temp;
	U32 TotalReadByte, WriteBlockCnt=0;
	U32 status;

	rd_cnt_HSMMC=0;	
	HS_DMA_END = 0;	
	BlockNum_HSMMC = 0;
	rd_cnt_HSMMC = 0;
	ReadBlockCnt_INT = 0;	

	printf("\nSD/MMC block Read test\n");

	printf("\n0:Polling Read   1:Interrupt Read   2:DMA Read");
	printf("\nSelect the test mode : ");
    
       Testmode=GetIntNum();
    	
	printf("\nInput Write Start block number : ");
	StartAddr = GetIntNum();
	Addr_temp = StartAddr;	

	while((BlockNum_HSMMC == 0) || (BlockNum_HSMMC > 65535))
	{
		printf("Input number of block[1~4095] : ");
		BlockNum_HSMMC = GetIntNum();
	}
	
	OneBlockSize = Card_OneBlockSize_ver1;

	Rx_buffer_HSMMC = (U32 *)SDI_Rx_buffer_HSMMC;
    	for(i=0 ; i<(OneBlockSize*BlockNum_HSMMC)/4 ; i++)	
		*(Rx_buffer_HSMMC+i) = 0x0;   	

	switch(Testmode)
		{
			case  POL_Ver1:
				printf("\nPolling mode data read\n");

				while (!IsCardInProgrammingState());

				SetBlockSizeReg(7, 512); // Maximum DMA Buffer Size, Block Size
				SetBlockCountReg(BlockNum_HSMMC); // Block Numbers to Write
				SetArgumentReg(StartAddr*512); // Card Address to Write

				if(BlockNum_HSMMC == 1)//single block
					{
						printf("Single block read\n");
						SetTransferModeReg(0, 1, 0, 1, 0);
						SetCommandReg(17, 0); // CMD17: Single-Read						
					}
				else//multi block
					{
						printf("Multi block read\n");
						SetTransferModeReg(1, 1, 1, 1, 0);
						SetCommandReg(18, 0); // CMD18: Multi-Read
					}

				while (!WaitForCommandComplete());
				ClearCommandCompleteStatus();
				
				for(j=0; j<BlockNum_HSMMC; j++)
					{
						if (!WaitForBufferReadReady())
							printf("ReadBuffer NOT Ready\n");
						else
							ClearBufferReadReadyStatus();
						for(i=0; i<512/4; i++)
						{
							*Rx_buffer_HSMMC++ = rHM_BDATA;
							rd_cnt_HSMMC++;
						}
						WriteBlockCnt ++;
						printf("\nWrite block count = %d", WriteBlockCnt);
					}

				TotalReadByte = wt_cnt_HSMMC *4;
				printf("\nWrite count=%dByte\n",TotalReadByte);
				
				printf("\nWrite count=%x\n",rd_cnt_HSMMC);
				if(!WaitForTransferComplete())
					{
					printf(("Transfer NOT Complete\n"));
					}
				ClearTransferCompleteStatus();

				break;

			case INT_Ver1:	
				
				printf("\Interrupt mode data Read\n");
				pISR_SDI_1=(unsigned)HS_READ_INT;
				
				SetBlockSizeReg(7, 512); // Maximum DMA Buffer Size, Block Size
				SetBlockCountReg(BlockNum_HSMMC); // Block Numbers to Write
				SetArgumentReg(StartAddr*512); // Card Address to Write

				if(BlockNum_HSMMC == 1)//single block
					{
						SetTransferModeReg(0, 1, 0, 1, 0);
						SetCommandReg(17, 0); // CMD17: Single-Read	
					}
				else//multi block
					{
						SetTransferModeReg(1, 1, 1, 1, 0);
						SetCommandReg(18, 0); // CMD18: Multi-Read						
					}
				
				if (!WaitForCommandComplete());
				ClearCommandCompleteStatus();

				printf("\nInterupt mode Read Start\n");
				rINTMSK &= ~(BIT_SDI1);
				rHM_NORINTSIGEN = rHM_NORINTSIGEN & ~(0xffff) | BUFFER_READREADY_SIG_INT_EN;	
				
				while(!READINT_DONE);
				
				if(!WaitForTransferComplete())
					{
					printf(("Transfer NOT Complete\n"));
					}
				ClearTransferCompleteStatus();

				printf("\nInterupt mode Read End\n");
				
	    			break;
					
			case DMA_Ver1:

				pISR_SDI_1=(unsigned)HS_DMA_INT;
				rINTMSK &= ~(BIT_SDI1);
				rHM_NORINTSTSEN &= ~(DMA_STS_INT_EN|BLOCKGAP_EVENT_STS_INT_EN);
				rHM_NORINTSIGEN = rHM_NORINTSIGEN & ~(0xffff) | TRANSFERCOMPLETE_SIG_INT_EN;
				
				SetSystemAddressReg(SDI_Rx_buffer_HSMMC);// AHB System Address For Write
				SetBlockSizeReg(7, 512); // Maximum DMA Buffer Size, Block Size				
				SetBlockCountReg(BlockNum_HSMMC); // Block Numbers to Write	
				SetArgumentReg(StartAddr*512);// Card Start Block Address to Write

				if (BlockNum_HSMMC == 1)
				{
					SetTransferModeReg(0, 1, 0, 1, 1);
					SetCommandReg(17, 0); // CMD17: Single-Read
				}
				else
				{	// (u32 MultiBlk, u32 DataDirection, u32 AutoCmd12En, u32 BlockCntEn, u32 DmaEn)
					SetTransferModeReg(1, 1, 1, 1, 1);
					SetCommandReg(18, 0); // CMD18: Multi-Read
				}

				if (!WaitForCommandComplete())
				{
					printf(("Command NOT Complete\n"));
				}
				else
					ClearCommandCompleteStatus();		
					

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -