📄 sd_cmd.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 + -