📄 sd_init.c
字号:
#ifndef SD_INIT_C
#define SD_INIT_C
/**************************************START OF THE FILE****************************************************************/
/************************************************************************************/
/* */
/* Copyright (C) 2004 Medeli Electric Industry Co., LTD. */
/* */
/* System Name : IC-1000 */
/* File Name : sd_init.c */
/* Revision : 1.00 */
/* Date : 2006/4/6 */
/* Initial version */
/* Joe's work */
/************************************************************************************/
/*******************************Constants************************************/
/**************************Variable Declaration******************************/
/********************************Locoal**************************************/
CUWORD sd_to_unit[8]=
{/* 超时时间单位表(单位:0.000000001ns) timeout unit table */
1000000000,100000000,10000000,1000000,100000,10000,1000,100
};
CUBYTE sd_to_value[16]=
{/* 超时时间表 timeout value table */
0,10,12,13,15,20,25,30,35,40,45,50,55,60,70,80
};
/*******************************External*************************************/
/**************************Function Declaration******************************/
/********************************Locoal**************************************/
/*******************************External*************************************/
/***************************Start of program*********************************/
/****************************************************************************/
/* initial sd card interface */
/* Function : init_sd */
/* Parameters */
/* Input : Nothing */
/* Output : Nothing */
/****************************************************************************/
UBYTE sd_card_initial(void)
{
UBYTE ini_trys;
UBYTE ret=SD_ERROR;
sio_set_baudrate(SIO_BAUDRATE_INI);
for(ini_trys=0;ini_trys<3;ini_trys++)
{
sd_interface_init();
if(sd_enter_idle() == SD_OK)
{
if(sd_card_activate() == SD_OK)
{
break;
}
}
}
if((ini_trys<3)&&(sd_read_ocr() == SD_OK))
{
if((sd_vars.ocr[1]&MSK_OCR_33) == MSK_OCR_33)
{
sio_set_baudrate(SIO_BAUDRATE_WORK);
if(sd_set_crc(0) == SD_OK)
{
if(sd_set_block_length(SD_BLOCK_LENGTH) == SD_OK)
{
if(sd_get_card_info() == SD_OK)
{
ret=SD_OK;
}
}
}
}
}
SD_CS_DEASSERT;
return ret;
}
/****************************************************************************/
/* initial sd card interface */
/* Function : init_sd */
/* Parameters */
/* Input : Nothing */
/* Output : Nothing */
/****************************************************************************/
UBYTE sd_card_activate(void)
{
UBYTE ret=SD_OK;
UWORD i=0;
sd_write_com_para(0,0,0,0);
for(i=0;(i<SD_IDLE_WAIT_MAX);i++)
{/* 如果响应R1的最低位Idle位为1,则继续循环 */
if(sd_send_cmd_idle(CMD55,sd_vars.com_para,0,sd_vars.resp)==SD_OK)
{
if(sd_send_cmd_idle(ACMD41,sd_vars.com_para,1,sd_vars.resp)==SD_OK)
{
if(!sd_vars.resp[0])
{
break;
}
}
}
}
if(i>= SD_IDLE_WAIT_MAX)
{/* 超时,返回错误 time out,return error */
ret=SD_ERROR;
}
return ret;
}
/****************************************************************************/
/* initial sd card interface */
/* Function : init_sd */
/* Parameters */
/* Input : Nothing */
/* Output : Nothing */
/****************************************************************************/
UBYTE sd_read_ocr(void)
{
UBYTE i,ret=SD_ERROR;
sd_write_com_para(0,0,0,0);
if(sd_send_cmd(CMD58,sd_vars.com_para,0,sd_vars.resp) == SD_OK)/* 读 OCR 寄存器命令 */
{
if(!sd_vars.resp[0])
{
for(i=0;i<4;i++)
{
sd_vars.ocr[i]=sd_vars.resp[i+1];
}
ret = SD_OK;
}
}
return ret;
}
/****************************************************************************/
/* initial sd card interface */
/* Function : init_sd */
/* Parameters */
/* Input : Nothing */
/* Output : Nothing */
/****************************************************************************/
UBYTE sd_set_crc(UBYTE enable)
{
UBYTE ret=SD_ERROR;
sd_write_com_para((enable)? 1:0,0,0,0);
if(sd_send_cmd(CMD59,sd_vars.com_para,0,sd_vars.resp)==SD_OK)
{/* "使能/禁止CRC"命令 */
if(!sd_vars.resp[0])
{
ret=SD_OK;
}
}
return ret;
}
/****************************************************************************/
/* initial sd card interface */
/* Function : init_sd */
/* Parameters */
/* Input : Nothing */
/* Output : Nothing */
/****************************************************************************/
UBYTE sd_set_block_length(UWORD block_length)
{
UBYTE ret=SD_ERROR;
sd_pack_com_para(sd_vars.com_para,block_length);
/* 将参数转化为字节形式 */
if(sd_send_cmd(CMD16,sd_vars.com_para,0,sd_vars.resp)==SD_OK)
{
if(!sd_vars.resp[0])
{
ret=SD_OK;
}
}
return ret;
}
/****************************************************************************/
/* initial sd card interface */
/* Function : init_sd */
/* Parameters */
/* Input : Nothing */
/* Output : Nothing */
/****************************************************************************/
UBYTE sd_read_register(UWORD len,UBYTE *save_pt)
{
UWORD i=0;
UHWORD crc16;
UBYTE ret=SD_ERROR;
do
{/* 等待数据起始令牌 wait for data start token */
sd_vars.resp[0] = sd_get_byte();
i++;
}while((sd_vars.resp[0]==0xff) && (i<SD_READREG_TIMEOUT));
if(i<SD_READREG_TIMEOUT)
{
if (sd_vars.resp[0]!=SD_TOK_READ_STARTBLOCK)
{/* 不是收到数据起始令牌 not receive data start token */
save_pt[0]=sd_vars.resp[0];
i=1;/* 还有len - 1个字节要接收 still len - 1 bytes will be received */
}
else
{/* 收到数据起始令牌,还有len个字节要接收 received data start token,still len bytes will be received */
i=0;
}
for( ; i<len; i++)
{/* 接收数据 receive data */
save_pt[i]=sd_get_byte();
}
/* 下面读取16位CRC get 16-bit CRC */
crc16=sd_get_byte();
crc16=(crc16<<8)+sd_get_byte();
#if SD_CRC_ENABLED
if (crc16==sd_get_crc16(save_pt,len))
{/* CRC校验正确 CRC check is correct */
ret=SD_OK;
}
#else
ret=SD_OK;
#endif
}
sd_send_byte(0xff);
/* 返回之前发送8个clock clock out 8 clk before return */
return ret;
}
/****************************************************************************/
/* initial sd card interface */
/* Function : init_sd */
/* Parameters */
/* Input : Nothing */
/* Output : Nothing */
/****************************************************************************/
UBYTE sd_read_csd(UBYTE csdlen, UBYTE *csd_pt)
{
UBYTE ret=SD_ERROR;
sd_write_com_para(0,0,0,0);
if(sd_send_cmd(CMD9,sd_vars.com_para,0,sd_vars.resp) == SD_OK)
{/* 读CSD寄存器命令 command that read CSD register */
if(!sd_vars.resp[0])
{
return (sd_read_register(csdlen, csd_pt));
}
}
return ret;
}
/****************************************************************************/
/* initial sd card interface */
/* Function : init_sd */
/* Parameters */
/* Input : Nothing */
/* Output : Nothing */
/****************************************************************************/
void sd_calc_timeout(UBYTE *csd_pt)
{
UWORD temp;
UBYTE time_u,time_v,fator;
sd_vars.timeout_read=READ_TIMEOUT_100MS;
/* 默认读超时为100ms */
sd_vars.timeout_write=WRITE_TIMEOUT_250MS;
/* 默认写超时为250ms */
sd_vars.timeout_erase=WRITE_TIMEOUT_250MS;
/* 默认擦除超时为250ms */
time_u=(sd_vars.csd[TAAC_POS]&TAAC_MSK);
/* 读超时时间单位 read timeout unit */
time_v=(sd_vars.csd[TAAC_POS]&NSAC_MSK) >> 3;
/* 读超时时间值 read timeout value */
fator=(sd_vars.csd[R2WFACTOR_POS]&R2WFACTOR_MSK)>>2;
/* 写超时时间因数 write timeout factor */
if((time_v)&&(fator<6))
{
temp=SIO_BAUDRATE_WORK * sd_to_value[time_v]/10/ sd_to_unit[time_u];
/* TACC * f (单位 unit: clock) */
temp=temp+csd_pt[NSAC_POS] * 100;
/* TACC * f + NSAC * 100 (单位 unit: clock) */
sd_vars.timeout_read=temp;
/* 计算得到的超时值 the timeout value of being calculated */
sd_vars.timeout_write=temp<<fator;
/* (TACC * f + NSAC * 100) * R2WFACTOR (单位 unit:clock)*/
sd_vars.timeout_read =sd_vars.timeout_read * 100/8;
/* 实际值为计算值的100倍 */
sd_vars.timeout_write=sd_vars.timeout_write * 100/8;
if(sd_vars.timeout_read>READ_TIMEOUT_100MS)
{/* 取计算值与默认值中的最小值 */
sd_vars.timeout_read=READ_TIMEOUT_100MS;
}
if(sd_vars.timeout_write>WRITE_TIMEOUT_250MS)
{/* 取计算值与默认值中的最小值 */
sd_vars.timeout_write=WRITE_TIMEOUT_250MS;
}
sd_vars.timeout_erase=sd_vars.timeout_write;
}
return;
}
/****************************************************************************/
/* initial sd card interface */
/* Function : init_sd */
/* Parameters */
/* Input : Nothing */
/* Output : Nothing */
/****************************************************************************/
UBYTE sd_get_card_info(void)
{
UBYTE i,ret=SD_ERROR;
UWORD temp;
if((ret=sd_read_csd(16,sd_vars.csd)) == SD_OK)
{/* 读CSD寄存器 read CSD register */
sd_calc_timeout(sd_vars.csd);
/* 计算超时时间值 calculate timeout value */
sd_vars.trans_speed=((sd_vars.csd[TRANS_SPEED_POS]&0x7f)>>3)*100000;
/* 计算传速 calculate the transfering speed of the card */
for((i=sd_vars.csd[TRANS_SPEED_POS]&0x07);i;i--)
{
sd_vars.trans_speed*=10;
}
sd_vars.block_len=1<<(sd_vars.csd[READ_BL_LEN_POS]&READ_BL_LEN_MSK);
/* 计算块的最大长度 calculate the size of a sector *//* (2 ^ READ_BL_LEN) */
sd_vars.block_num = ((sd_vars.csd[C_SIZE_POS1]&C_SIZE_MSK1)<<10) + (sd_vars.csd[C_SIZE_POS2]<<2) + ((sd_vars.csd[C_SIZE_POS3]&C_SIZE_MSK3)>>6) + 1;/* (C_SIZE + 1)*/
/* 计算卡中块的个数 calculate the sector numbers of the SD Card */
temp=((sd_vars.csd[C_SIZE_MULT_POS1]&C_SIZE_MULT_MSK1)<<1) +((sd_vars.csd[C_SIZE_MULT_POS2]&C_SIZE_MULT_MSK2)>>7)+2;/* (C_SIZE_MULT + 2) */
/* 获得卡中块的数量 get the block numbers in card */
sd_vars.block_num=sd_vars.block_num * (1<<temp);
/* (C_SIZE + 1) * 2 ^ (C_SIZE_MULT + 2) */
sd_vars.erase_unit=((sd_vars.csd[SECTOR_SIZE_POS1]&SECTOR_SIZE_MSK1)<<1) + ((sd_vars.csd[SECTOR_SIZE_POS2]&SECTOR_SIZE_MSK2)>>7) + 1;/* SD (SECTOR_SIZE + 1) */
/* 计算扇区大小 calculate the size of sector */
}
return ret;
}
/****************************************************************************/
/* initial sd card interface */
/* Function : init_sd */
/* Parameters */
/* Input : Nothing */
/* Output : Nothing */
/****************************************************************************/
void sd_interface_init(void)
{
rPDATE&=~(1<<8);/* 对卡断电 */
sd_vars.timer=0;
rPDATC|=(1<<15);/* 245 cs deassert */
SD_CS_DEASSERT;
sio_set_baudrate(SIO_BAUDRATE_INI);
while(sd_vars.timer<5);
rPDATE|=(1<<8);/* 对卡上电 */
sd_vars.timer=0;
rPDATC&=~(1<<15);/* 245 cs assert */
while(sd_vars.timer<5);
SD_CS_ASSERT;
sd_delay(250);
SD_CS_DEASSERT;
sd_delay(100);
SD_CS_ASSERT;
sd_vars.timer=0;
rPDATC&=~(1<<15);/* 245 cs assert */
while(sd_vars.timer<5);
return;
}
/****************************************************************************/
/* initial sd card interface */
/* Function : init_sd */
/* Parameters */
/* Input : Nothing */
/* Output : Nothing */
/****************************************************************************/
UBYTE sd_enter_idle(void)
{
UBYTE ret=SD_ERROR;
if(sd_send_cmd_idle(CMD0,sd_vars.com_para,0,sd_vars.resp)==SD_OK)
{
if(sd_vars.resp[0]==B_MSK_IDLE)
{
ret=SD_OK;
}
}
return ret;
}
/****************************************END OF THE FILE****************************************************************/
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -