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

📄 sd.c

📁 S3C2440开发板SD驱动程序。ADS1.2源码
💻 C
📖 第 1 页 / 共 3 页
字号:

/*
*********************************************************
*   					 头文件
*********************************************************
*/
#include <stdio.h>
#include <string.h>
#include "def.h"
#include "option.h"
#include "2440addr.h"
#include "2440lib.h"
#include "sd.h"

#define INICLK	300000		//初始频率
#define SDCLK	24000000	//PCLK=49.392MHz
#define MMCCLK	15000000	//PCLK=49.392MHz
 
#define MAX_DATABUSY_TIMEOUT			0x007FFFFF

#define WORDS_PER_BLOCK					128
#define MAX_RWBUFFER_BLOCKNUM			16

#define Tx_buffer	(unsigned int *)0x31700000	//读写缓冲地址
#define Rx_buffer	(unsigned int *)0x31800000

#define POL	0
#define INT	1
#define DMA	2


#define Wide	ENUM_SD_BUS_4_BIT	// 总线位数

/*
*********************************************************
*   					 变量
*********************************************************
*/

volatile U32 			SD_CardIn = 0;		//SD卡插入中断标志
volatile U32			TR_end =0;		//数据传输完成标志

/*
*********************************************************
*   					 函数
*********************************************************
*/

int Check_Card_In(void)
{
	int CardIn;
	U32	save_rGPGCON = rGPGCON;
	
	rGPGCON = (rGPGCON & 0xfffcffff); 				// CDSD,GPG8 =>In
	Delay(50);
	
	if(rGPGDAT & (1<<8))
	{
		CardIn = 0;
	}
	else
	{
		CardIn = 1;
	}
	
	rGPGCON = save_rGPGCON;
	
	return CardIn;
}

static void SD_Set_IOPort(void)
{
	rGPECON = ((rGPECON & 0xffb003ff) | 0xffeaabff);	// SDCLK, SDCMD, SDDAT[3:0]
    rGPEUP  = (rGPEUP & 0xf83f);     					// SDCMD, SDDAT[3:0] => PU En.
}

void SD_Config_Irq(void) //Config SD Irq --wangq
{
	rGPGCON = (rGPGCON & (0<<16) | (1<<17)); 			// CDSD,GPG8 =>EINT[16]	
	rGPGUP = rGPGUP & (~(0x1<<8));						// Enable pullup
	rEXTINT2 = (1<<3) + 2;								// EINT16 Filter Enable,Falling edge triggered
	rEINTFLT2 = (rEINTFLT2 & (0<<7) | 0x7f);			// PCLK,Filtering width=0x3f
	rEINTMASK =  ~(1<<16); 								// Enable EINT16 interrupt	

	ClearPending(BIT_EINT8_23);
	
    rINTMSK = ~(BIT_EINT8_23); 							// Enable EINT8_23 interrupt 
    
    //Uart_Printf("Config SD Irq Complete----------!\n");
}

static int Chk_CMDend(int cmd, int be_resp)
{
    int finish0;

    if(!be_resp)    // No response
    {
    	finish0 = rSDICSTA;
		while((finish0 & 0x800) != 0x800)	// Check cmd end
		{
	    	finish0 = rSDICSTA;
	    }

		rSDICSTA = finish0;// Clear cmd end state

		return 1;
    }
    else	// With response
    {
    	finish0 = rSDICSTA;
		while( !( ((finish0&0x200)==0x200) | ((finish0&0x400)==0x400) ))    // Check time/rsp end
	//	while( !( ((finish0&0x200)==0x200) | ((finish0&0x400)==0x800) ))	// Check cmd/rsp end	
		{
			finish0 = rSDICSTA;
		}
		//Uart_Printf("CMD%d:rSDICSTA=0x%x\n", cmd, rSDICSTA);	//YH 0811

		if((cmd==1) | (cmd==41))	// CRC no check, CMD9 is a long Resp. command.

		{
		    if( (finish0 & 0xf00) != 0xa00 )  // Check error
		    {
				//Uart_Printf("Error:  CMD%d:rSDICSTA=0x%x, rSDIRSP0=0x%x\n",cmd, rSDICSTA, rSDIRSP0);
				rSDICSTA=finish0;   // Clear error state

				if(((finish0&0x800) == 0x800))
				{
			    	return 1;	// CMD end
			    }
				if(((finish0&0x400) == 0x400))
				{
			    	return 0;	// Timeout error
			    }
	    	 }
	    	 
		    rSDICSTA = finish0;	// Clear cmd & rsp end state
		}
		else	// CRC check
		{
			
		    if( (finish0&0x1f00) != 0xa00 )	// Check error
		    {
				//Uart_Printf("Error:  CMD%d:rSDICSTA=0x%x, rSDIRSP0=0x%x\n",cmd, rSDICSTA, rSDIRSP0);
				rSDICSTA = finish0;   	// Clear error state
			
				if((finish0 & 0x400) == 0x400)
				{
			    	return 0;			// Timeout error
			    }
	    	}
	    	//Uart_Printf("ok:  CMD%d:rSDICSTA=0x%x, rSDIRSP0=0x%x\n",cmd, rSDICSTA, rSDIRSP0);
		    rSDICSTA = finish0;
		}
	
		return 1;
    }
}

static void CMD0(void)
{
    //-- Make card idle state 
    rSDICARG = 0x0;	    		// CMD0(stuff bit)
    rSDICCON = (1<<8) | 0x40;   // No_resp, start, CMD0

    //-- Check end of CMD0
    Chk_CMDend(0, 0);
    rSDICSTA = 0x800;	    	// Clear cmd_end(no rsp)
}

static int CMD8(void)//SEND_IF_COND
{
    int i = 0;
    for (i = 0; i < 50; i++)			//CMD8
    {    	
    	rSDICARG = 0x1AA;						//CMD8(SD VHS:2.7V~3.6V)
    	rSDICCON = (0x1<<9) | (0x1<<8) | 0x48;	//sht_resp, wait_resp, start, CMD8

    	if ( Chk_CMDend(8, 1) & (rSDIRSP0 == 0x1aa) )
    	{	
    		rSDICSTA = 0xa00;		// Clear cmd_end(with rsp)
			return 1;
		}
		Delay(200); 			// Wait Card power up status
	}
	return 0;
}

static int CMD2(void)// ALL_SEND_CID
{
	int  Serial_Num;	//SD卡ID
	
	rSDICARG = 0x0;   		// CMD2(stuff bit)
    rSDICCON = (0x1<<10) | (0x1<<9) | (0x1<<8) | 0x42; //lng_resp, wait_resp, start, CMD2

    //-- Check end of CMD2
    if(!Chk_CMDend(2, 1)) 
    {
		return 0;			// Fail
	}
    rSDICSTA = 0xa00;		// Clear cmd_end(with rsp)

	Serial_Num = ((rSDIRSP2&0xffffff) << 8) | ((rSDIRSP3&0xff000000) >> 24);   
    Uart_Printf("Card Id  = 0x%x\n",Serial_Num);
    //Uart_Printf("Capacity = %c%c%c\n",(rSDIRSP1&0xff0000)>>16,(rSDIRSP1&0xff00)>>8,rSDIRSP1&0xff);
    Uart_Printf("The manufacturing date is %d.%d\n",2000+((rSDIRSP3&0xff000)>>12) ,(rSDIRSP3&0xf00)>>8);
    
	return Serial_Num;		// Success
}

static int CMD3(void)		// SEND_RCA
{
    rSDICARG = 0x0;	    				// CMD3(MMC:Set RCA, SD:Ask RCA-->SBZ)
    rSDICCON = (0x1<<9)|(0x1<<8)|0x43;	// sht_resp, wait_resp, start, CMD3

    //-- Check end of CMD3
    if(!Chk_CMDend(3, 1)) 
    {
		return 0;
	}
    rSDICSTA = 0xa00;						// Clear cmd_end(with rsp)
	
    return 1;
}

static int Chk_MMC_OCR(void)
{
    int i;

    //-- Negotiate operating condition for MMC, it makes card ready state
    for(i = 0; i < 50; i++)	//Negotiation time is dependent on CARD Vendors.
    {
		//rSDICARG=0xffc000;	    	    //CMD1(MMC OCR:2.6V~3.6V)
		rSDICARG = 0xff8000;	    	    	//CMD1(SD OCR:2.7V~3.6V)
    	rSDICCON = (0x1<<9)|(0x1<<8)|0x41;    	//sht_resp, wait_resp, start, CMD1

    	//-- Check end of CMD1
		if(Chk_CMDend(1, 1) && (rSDIRSP0>>16)==0x80ff) //YH 0903 [31]:Card Power up status bit (busy)
		//if(Chk_CMDend(1, 1) & rSDIRSP0==0x80ff8000) 
		{
		    rSDICSTA = 0xa00;	// Clear cmd_end(with rsp)
		    return 0;			// Success,MMC
		}
    }
    rSDICSTA = 0xf00;	// Clear cmd_end(with rsp)
    return 1;			// Fail,SD
}

static int CMD55(int iRCA)
{
    //--Make ACMD
    rSDICARG = iRCA<<16;					//CMD7(RCA,stuff bit)
    rSDICCON = (0x1<<9) | (0x1<<8) | 0x77;	//sht_resp, wait_resp, start, CMD55

    //-- Check end of CMD55
    if(!Chk_CMDend(55, 1)) 
    {
		return 0;
	}

    rSDICSTA = 0xa00;	// Clear cmd_end(with rsp)
    return 1;
}

static int Chk_SD_OCR(void)	//ACMD41
{
    int i;
    
    //-- Negotiate operating condition for SD, it makes card ready state
    
    for(i=0;i<50;i++)			//If this time is short, init. can be fail.
    {			
		//-- 检测是否为SDHC
    	CMD55(0);    			// Make ACMD
    	rSDICARG = 0xc0ff8000;	//ACMD41(SD OCR:2.7V~3.6V,HCS=1)
		//rSDICARG=0xffc000;	//ACMD41(MMC OCR:2.6V~3.6V)
    	rSDICCON = (0x1<<9)|(0x1<<8)|0x69;//sht_resp, wait_resp, start, ACMD41

		//-- Check end of ACMD41
    	if( Chk_CMDend(41, 1) && (rSDIRSP0==0xc0ff8000) ) 
		{
			Uart_Printf("SDHC Card...\n");
		    rSDICSTA = 0xa00;		// Clear cmd_end(with rsp)		
		    return 1;			// Success	    
		}
		
		//-- 检测是否为SD1.0
		CMD55(0);    			// Make ACMD
    	rSDICARG = 0x80ff8000;	//ACMD41(SD OCR:2.7V~3.6V,HCS=0)
    	rSDICCON = (0x1<<9) | (0x1<<8) | 0x69;//sht_resp, wait_resp, start, ACMD41

		//-- Check end of ACMD41
    	if( Chk_CMDend(41, 1) && (rSDIRSP0==0x80ff8000) ) 
		{
			Uart_Printf("SD1.0 Card...\n",rSDIRSP0);
		    rSDICSTA = 0xa00;		// Clear cmd_end(with rsp)		
		    return 2;			// Success	    
		}
		
		Delay(200); 			// Wait Card power up status		
			
    }
        
    Uart_Printf("Error: ACMD41 SDIRSP0=0x%x\n",rSDIRSP0);
    rSDICSTA = 0xa00;	// Clear cmd_end(with rsp)
    return 0;		// Fail
}

int Card_Select( int iRCA)
{
    //-- Card select
    int i = 0;
	do
	{	
		rSDICARG = iRCA<<16;					// CMD7(RCA,stuff bit)
		rSDICCON = (0x1<<9) | (0x1<<8) | 0x47;  // sht_resp, wait_resp, start, CMD7
		i++;
	}
	//-- Check end of CMD7
	while(!Chk_CMDend(7, 1) && (i < 100));

	rSDICSTA = 0xa00;			// Clear cmd_end(with rsp)

	if (i == 100)
	{
		return 0;
	}
	
	//--State(transfer) check
	if( (rSDIRSP0 & 0x1e00) != 0x800 )
	{
	    return 0;
	}
	return 1;
}

int Card_Deselect( void)
{
	//-- Card deselect
	int i = 0;
	do
	{	
		rSDICARG = 0<<16;			//CMD7(RCA,stuff bit)
		rSDICCON = (0x1<<8)|0x47;	//no_resp, start, CMD7
		i++;
	}
	//-- Check end of CMD7
	while(!Chk_CMDend(7, 0) && (i < 100));

	rSDICSTA = 0x800;			// Clear cmd_end(no rsp)
	if (i == 100)
	{
		return 0;
	}
	
	return 1;
}

static int CMD9(int iRCA)	//SEND_CSD
{
   Card_Deselect();	// Card deselect
    
    rSDICARG = iRCA<<16;								// CMD9(RCA,stuff bit)
    rSDICCON = (0x1<<10)|(0x1<<9)|(0x1<<8)|0x49;	// long_resp, wait_resp, start, CMD9
    
    //-- Check end of CMD9
    if (!Chk_CMDend(9, 1)) 
    {
		return 0;
	}
	if ((rSDIRSP0&0xf0000000)>>28 == 4)				//CSD Version 2.0
	{
		Uart_Printf("Memory Capacity= %dMB\n",( (rSDIRSP2&0xffff0000)>>16 )>>1 );
	}
	else if ((rSDIRSP0&0xf0000000)>>28 == 0)		//CSD Version 1.0
	{
		Uart_Printf("Memory Capacity= %dMB\n",(((rSDIRSP1&0x3ff)<<2) | (rSDIRSP2&0xc0000000))>>1);
	}
	
	//Uart_Printf("CSD register :\n");
    //Uart_Printf("SDIRSP0=0x%x\nSDIRSP1=0x%x\nSDIRSP2=0x%x\nSDIRSP3=0x%x\n", rSDIRSP0,rSDIRSP1,rSDIRSP2,rSDIRSP3);
    
    Card_Select(iRCA);	// Card select
    	
    return 1;
}

static int SetBus(int iRCA,enum_sd_bus_width iWide)
{
	int i = 0;
	do
	{
	    CMD55(iRCA);	// Make ACMD
	    //-- CMD6 implement
	    rSDICARG = iWide << 1;	    			//Wide 0: 1bit, 1: 4bit
	    rSDICCON = (0x1 << 9) | (0x1 << 8) | 0x46;	//sht_resp, wait_resp, start, CMD46
	    i++;
	}
    while((i < 50) && (!Chk_CMDend(6, 1)));   	// ACMD6
    
    rSDICSTA = 0xa00;	    // Clear cmd_end(with rsp)   
    
    if (i < 50)
    {	   
    	if (iWide)
    	{  
	    	Uart_Printf("**** 4bit bus ****\n");
	    }
    	else
    	{
    		Uart_Printf("**** 1bit bus ****\n");
    	}
	    return	1;
    }
    else
    {
    	return 0;
    }
}

static int Set_1bit_bus(int iRCA)
{    
   	int i = 0;
	do
	{
	    CMD55(iRCA);	// Make ACMD
	    //-- CMD6 implement
	    rSDICARG = 0 << 1;	    				//Wide 0: 1bit, 1: 4bit
	    rSDICCON = (0x1<<9) | (0x1<<8) | 0x46;	//sht_resp, wait_resp, start, CMD46
	    i++;
	}

⌨️ 快捷键说明

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