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

📄 sd_cmd.c

📁 基于U(375)盘及SD(SPI模式)卡集成文件系统(包括底层驱动)
💻 C
字号:
#include "sd_cmd.h"
#include "Driver_WR.h"
#define SECTOR_32M 64*1024
#define READ_TIMEOUT_100MS 400*1024*1024/10
#define WRITE_TIMEOUT_250MS 400&1024*1024/4
#define SPI_CLOCK 1

volatile DSTATUS Stat = STA_NOINIT;

volatile unsigned char CardType; // b1:MMC, b2:SDv1, b3:SDv2, b4:Block addressing //

csd_struct csds;
sd_struct sds;

/* 超时时间单位表(单位:0.000000001ns) timeout unit table */
const UINT32 time_unit[8] = {1000000000,100000000,10000000,
							 1000000,100000,10000,1000,100};

/* 超时时间表 timeout value table */							 
const UINT8 time_value[16] = {0,10,12,13,15,20,25,30,
                              35,40,45,50,55,60,70,80};
 
/* 超时时间因数表 timeout factor table */                              
const UINT8 r2w_fator[6] = {1,2,4,8,16,32};  

UINT8 ocr[4]; //operating condition 
/********************************************************************************************************************
** 函数名称: UINT8 Write_Command_MMC(UINT8 cmd, UINT32 address)
** Name:	 UINT8 Write_Command_MMC(UINT8 cmd, UINT32 address)
** 功能描述: 写入命令				          
** Function: Write Command to MMC/SD Card
** 输   入: UINT8 cmd : 输入命令值
			 UINT32 address:输入命令参数
** Input:    UINT8 cmd : The Value of the command
			 UINT32 address:the argument of the command
** 输   出: 状态字 	  		  
** Output:	 Response  of the command
*********************************************************************************************************************/
UINT8 Write_Command_MMC(UINT8 cmd, UINT32 address)
{
	UINT32 retry=100;
	UINT8 tmp;
	UINT8 crcc = 0xFF;
	if(cmd&0x80)
	{
		cmd &=0x7F;
		tmp = Write_Command_MMC(CMD55,0);
		if(tmp>1)
			return tmp;
	}
	SPI_TransferByte(0xff);
	
	tmp = SPI_TransferByte(cmd);
	tmp = SPI_TransferByte(address>>24);
	tmp = SPI_TransferByte(address>>16);
	tmp = SPI_TransferByte(address>>8);
	tmp = SPI_TransferByte(address);
	if(cmd == CMD0) crcc = 0x95;
	if(cmd == CMD8) crcc = 0x87;
	tmp = SPI_TransferByte(crcc);   
	
	if(cmd == CMD12) SPI_TransferByte(0xff);
	
	do{
		tmp = SPI_TransferByte(0xFF);
		--retry;
	}while((tmp&0x80)&&retry);   //  等待返回或者计时时间到达
	if(!retry)
		printf("Error: CMD%d, \n",(cmd-64));
	if(cmd == CMD17)
		crcc = 0xff;
	if((cmd == CMD25)||(cmd == CMD24))
		crcc = 0xff;
	return(tmp);
}


/********************************************************************************************************************
** 函数名称: UINT8 MMC_Init()
** Name:	 UINT8 MMC_Init()
** 功能描述: MMC/SD卡初始化					          
** Function: Initialize the MMC/SD Card
** 输   入: 无
** Input:    NULL
** 输   出: 0: 初始化成功, 1:初始化失败 	  		  
** Output:	 0: Success      1: Fail 
*********************************************************************************************************************/

UINT8 MMC_Init()
{

    UINT8 i;
    UINT8 ty;
    UINT8 cmd;
    UINT32 Timer1;
    if(Stat & STA_NODISK) return Stat;
    MyMcbsp_Init();
    for (i=0;i<25;i++)
    {
    	SPI_TransferByte(0xff);     //1、至少延时74 clock delay more than 74 clock
    }
    //复位为idle 
    if(Write_Command_MMC(CMD0,0)==0x01)   //2、发出CMD0命令复位SD卡 Reset SD Card 
    {
    	Timer1 = 10000;
    		if(Write_Command_MMC(ACMD41, 0)<=1)  //3、发出激活命令
    		{
    			ty = 2; cmd = ACMD41;
    		}
    		else
    		{
    			ty = 1;
    			cmd = CMD1;
    		}
    		while(--Timer1 && Write_Command_MMC(cmd,0));  //重复发出激活命令
    		if(Write_Command_MMC(CMD58,0)==0)  
    		{
    			rcvr_datablock(ocr, 4);
    			if((ocr[1]&&0xC0)!=0xC0)             //4、不支持3.0 - 3.3v
    			{
    				Stat = STA_NOINIT;
    				return Stat;
    			}
    		}
    		else
    		{
    			Stat = STA_NOINIT;
    			return Stat;
    		}
    		SPI_ClkToMax();                         //5、设置SPI的clock到最大值
    		if(!Timer1 || Write_Command_MMC(CMD16, 512) !=0)  //6、设置Block长度 512字节
    			ty = 0;
    }
    CardType = ty;
    if(ty)
    {
    	Stat = STA_INITED;
    	return Stat;
    }
    else
    {
    	Stat = STA_NOINIT;
    	return Stat;
    }	
}
/********************************************************************************************************************
** 函数名称: UINT8 SD_Hiden32M(UINT32 mHidenVolume)
** Name:	 UINT8 SD_Hiden32M(UINT32 mHidenVolume)
** 功能描述: 隐藏SD卡中最后的32M空间					          
** Function: Hide 32M memory space
** 输   入: UINT32 mHidenVolume :隐藏的容量
** Input:    UINT32 mHidenVolume :The Volume to hide
** 输   出:  	  		  
** Output:	  
*********************************************************************************************************************/

UINT8 SD_Hiden32M(UINT32 mHidenVolume)
{
	UINT8* pSector;
	UINT32 TotalVolume;
	UINT32 FAT1_TotalVolume;
	UINT32 FAT2_TotalVolume;
	UINT32 nNewVolume;
	UINT32 temp32;
	UINT8  temp8;
	pSector = (UINT8*)MEM_alloc(0,512,0);
	
	temp8 = RBC_Read(0,1,pSector);
	if(temp8!=CH_OK)
	{
		MEM_free(0,pSector,512);
		return 1;
	}
	if(pSector[0x1FC]=='H' && pSector[0x1FD]=='W')
	{
		MEM_free(0,pSector,512);
		return 0;
	}
	else
	{
		temp32 = pSector[0x1C6] + (pSector[0x1C7]<<8) + (pSector[0x1C8]<<16) + (pSector[0x1C9]<<24);   //FAT1 address
		TotalVolume = pSector[0x1CA] + (pSector[0x1CB]<<8) + (pSector[0x1CC]<<16) + (pSector[0x1CD]<<24);
		nNewVolume = TotalVolume - SECTOR_32M;
		pSector[0x1CA] = nNewVolume & 0xFF;
		pSector[0x1CB] = (nNewVolume>>8) & 0xFF;
		pSector[0x1CC] = (nNewVolume>>16) & 0xFF;
		pSector[0x1CD] = (nNewVolume>>24) & 0xFF;
		pSector[0x1FC] = 'H';
		pSector[0x1FD] = 'W';
		temp8 = RBC_Write(0,1,pSector);
		if(temp8!=CH_OK)
		{
			MEM_free(0,pSector,512);
			return 1;
		}
	
		temp8 = RBC_Read(temp32,1,pSector);
		if(temp8!=CH_OK)
		{
			MEM_free(0,pSector,512);
			return 1;
		}
		FAT1_TotalVolume = pSector[0x20] + (pSector[0x21]<<8) + (pSector[0x22]<<16) + (pSector[0x23]<<24);
		nNewVolume = FAT1_TotalVolume - SECTOR_32M;
		pSector[0x1CA] = nNewVolume & 0xFF;
		pSector[0x1CB] = (nNewVolume>>8) & 0xFF;
		pSector[0x1CC] = (nNewVolume>>16) & 0xFF;
		pSector[0x1CD] = (nNewVolume>>24) & 0xFF;
		temp8 = RBC_Write(temp32,1,pSector);
		if(temp8!=CH_OK)
		{
			MEM_free(0,pSector,512);
			return 1;
		}
		
		temp32 = 6+temp32;
		RBC_Read(temp32,1,pSector);
		if(temp8!=CH_OK)
		{
			MEM_free(0,pSector,512);
			return 1;
		}
		FAT2_TotalVolume = pSector[0x20] + (pSector[0x21]<<8) + (pSector[0x22]<<16) + (pSector[0x23]<<24);
		nNewVolume = FAT2_TotalVolume - SECTOR_32M;
		pSector[0x1CA] = nNewVolume & 0xFF;
		pSector[0x1CB] = (nNewVolume>>8) & 0xFF;
		pSector[0x1CC] = (nNewVolume>>16) & 0xFF;
		pSector[0x1CD] = (nNewVolume>>24) & 0xFF;
		temp8 = RBC_Write(temp32,1,pSector);
		if(temp8!=CH_OK)
		{
			MEM_free(0,pSector,512);
			return 1;
		}
		else
		{
			MEM_free(0,pSector,512);
			return 0;
		}
	}
}
/********************************************************************************************************************
** 函数名称: int SD_EraseBlock(UINT32 Sector_start, UINT32 Sector_count)
** Name:	 int SD_EraseBlock(UINT32 Sector_start, UINT32 Sector_count)
** 功能描述: 擦除SD卡					          
** Function: Erase the block in SD Card
** 输   入: UINT32 Sector_start:擦除开始扇区号
** Input:    UINT32 Sector_count :擦除扇区数
** 输   出:  0:成功   1: 失败	  		  
** Output:	  0: Success  1: Fail
*********************************************************************************************************************/
int SD_EraseBlock(UINT32 Sector_start, UINT32 Sector_count)
{
	UINT32 address;
	UINT32 temp32;

	if(Sector_start+Sector_count>sds.block_num)
		return -1;
	else
	{
		address = Sector_start << 9;
		temp32 = Write_Command_MMC(CMD32 , address);
		address = (Sector_start + Sector_count -1)<<9;
		temp32 = Write_Command_MMC(CMD33 , address);
		temp32 = Write_Command_MMC(CMD38 , 0);
	}

	return 1;
}


/*******************************************************************************************************************
** 函数名称: INT8U SD_CalTimeout()				Name:	  INT8U SD_CalTimeout()
** 功能描述: 计算读/写/擦超时时间				Function: get the information of SD card
** 输   入: INT8U cardtype: 卡类型				Input:    INT8U cardtype: card type	
			 INT8U *csdbuf : CSD寄存器内容		 	      INT8U *csdbuf : CSD register content
** 输   出: 0:   正确    >0:   错误码		  	Output:	  0:  right		>0:  error code
*******************************************************************************************************************/
void SD_CalTimeout()
{
	UINT32 tmp;
	UINT8 time_u,time_v,fator;
	
	sds.timeout_read = READ_TIMEOUT_100MS;								/* 默认读超时为100ms */
	sds.timeout_write = WRITE_TIMEOUT_250MS;							/* 默认写超时为250ms */
	sds.timeout_erase = WRITE_TIMEOUT_250MS;
		
	time_u = csds.TAAC;								/* 读超时时间单位 read timeout unit */
	time_v = csds.NSAC;						/* 读超时时间值   read timeout value */
	fator = csds.R2W_FACTOR;				/* 写超时时间因数 write timeout factor */
	
	if(time_v == 0)	return;
	if(fator >= 6) return;
	
	tmp = SPI_CLOCK * time_value[time_v] / 10 / time_unit[time_u];		/* TACC * f (单位 unit: clock) */
	tmp = tmp + csds.NSAC * 100;									/* TACC * f + NSAC * 100 (单位 unit: clock) */
	
	/* 计算得到的超时值 the timeout value of being calculated */
	sds.timeout_read = tmp;
	sds.timeout_write = tmp * r2w_fator[fator];							/* (TACC * f + NSAC * 100) * R2WFACTOR (单位 unit:clock)*/
	
	sds.timeout_read  = sds.timeout_read * 100 / 8;						/* 实际值为计算值的100倍 */
	sds.timeout_write = sds.timeout_write * 100 / 8;
	
	if (sds.timeout_read > READ_TIMEOUT_100MS)							/* 取计算值与默认值中的最小值 */
		sds.timeout_read = READ_TIMEOUT_100MS;
	
	if (sds.timeout_write > WRITE_TIMEOUT_250MS)
		sds.timeout_write = WRITE_TIMEOUT_250MS;

	sds.timeout_erase = sds.timeout_write;
}

void Get_SD_Info()
{
	UINT32 temp32;
	UINT8 csdbuf[16];
	UINT8 n;
	UINT32 csize;		
			if (0) {			/* SDC ver 2.00 */
				if (Write_Command_MMC(ACMD13, 0) == 0) 
				{		/* Read SD status */
					SPI_TransferByte(0xff);
					rcvr_datablock(csdbuf, 16);
				}
			} 
			else 
			{					/* SDC ver 1.XX or MMC */
				if(    (Write_Command_MMC(CMD9, 0) == 0)  )
				{
					rcvr_datablock(csdbuf, 16);
					SPI_TransferByte(0xff);
					SPI_TransferByte(0xff);  
				}
				else
				{
					printf("Error: CMD9 \n");
					return;
				}
			}
			
			
			n = (csdbuf[5] & 15) + ((csdbuf[10] & 128) >> 7) + ((csdbuf[9] & 3) << 1) + 2;
					csize = (csdbuf[8] >> 6) + ((int)csdbuf[7] << 2) + ((int)(csdbuf[6] & 3) << 10) + 1;
					temp32 = (int)csize << (n - 9);
			
			csds.CSD_STRUCTURE = (csdbuf[0]&0xc0)>>6;
			csds.TAAC = csdbuf[1];
			csds.NSAC = csdbuf[2];
			csds.TRAN_SPEED = csdbuf[3];
			csds.CCC = (csdbuf[4]<<4)|((csdbuf[5]&0xF0)>>4);
			csds.READ_BL_LEN = csdbuf[5]&0x0F;
			csds.READ_BL_PARTIAL = (csdbuf[6]&0x80)>>7;
			csds.WRITE_BLK_MISALIGN = (csdbuf[6]&0x40)>>6;
			csds.READ_BLK_MISALIGN = (csdbuf[6]&0x20)>>5;
			csds.DSR_IMP = (csdbuf[6]&0x10)>>4;
			csds.C_SIZE = ((csdbuf[6]&0x03)<<10)|(csdbuf[7]<<2)|((csdbuf[8]&0xC0)>>6);
			csds.VDD_R_CURR_MIN = (csdbuf[8]&0x38)>>3;
			csds.VDD_R_CURR_MAX = (csdbuf[8]&0x07);
			csds.VDD_W_CURR_MIN = (csdbuf[9]&0xE0)>>5;
			csds.VDD_W_CURR_MAX = (csdbuf[9]&0x16)>>2;
			csds.C_SIZE_MULT = ((csdbuf[9]&0x03)<<1) + ((csdbuf[10]&0x80)>>7);
			csds.ERASE_BLK_EN = (csdbuf[10]&0x40)>>6;
			csds.SECTOR_SIZE = ((csdbuf[10]&0x3F)<<1) + ((csdbuf[11]&0x80)>>7);
			csds.WP_GRP_SIZE = (csdbuf[11]&0x7F);
			csds.WP_GRP_ENABLE = (csdbuf[12]&0x80)>>7;
			csds.R2W_FACTOR = (csdbuf[12]&0x16)>>2;
			csds.WRITE_BL_LEN = (csdbuf[12]&0x03)<<2 + ((csdbuf[13]&60)>>6);
			csds.WRITE_BL_PARTIAL = (csdbuf[13]&0x20)>>5;
			csds.FILE_FORMAT_GRP = (csdbuf[14]&0x80)>>7;
			csds.COPY = (csdbuf[14]&0x40)>>6;
			csds.PERM_WRITE_PROTECT = (csdbuf[14]&0x20)>>5;
			csds.TMP_WRITE_PROTECT = (csdbuf[14]&0x10)>>4;
			csds.FILE_FORMAT = (csdbuf[14]&0x06)>>2;
			csds.CRC = (csdbuf[15]&0x7F)>>1;
			
			SD_CalTimeout();
			
			sds.block_len = 1 << csds.READ_BL_LEN;  			/* (2 ^ READ_BL_LEN) */
	
			/* 计算卡中块的个数 */														/* calculate the sector numbers of the SD Card */
			sds.block_num = csds.C_SIZE + 1;				/* (C_SIZE + 1)*/
		 	  															
			temp32 = csds.C_SIZE_MULT + 2;				/* (C_SIZE_MULT + 2) */
    	
   		 	/* 获得卡中块的数量 */														/* get the block numbers in card */
			sds.block_num = sds.block_num * (1 << temp32);									/* (C_SIZE + 1) * 2 ^ (C_SIZE_MULT + 2) */
																			
			/* 计算扇区大小 */															/*calculate the size of sector */
			sds.erase_unit = csds.SECTOR_SIZE + 1; /* SD (SECTOR_SIZE + 1) */
			
}

⌨️ 快捷键说明

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