#include "..\define.h"
#include "..\all.h"
data bit gc_SysCardInsert;
data bit SDHC=0;
xdata U8 gc_SD_OCR[4];
xdata U8 gc_SD_RCA[2];
xdata U8 gc_SD_CID[16];
xdata U8 gc_SD_CSD[16];
xdata U32 gw_SD_BlockNum;
xdata U16 gw_SD_BlockSize;
xdata U16 gw_WaitTimeOut;
extern data U8 gc_SectorUnit;
extern xdata U32 gdw_DOS_SectorPerCard;
void SD_SetClock(U8 ClockValue);
void SdDetect(void);
void CommandToSd(U8 *ComBuff);
void SdTxDummy(void);
void SDWaitIdle(void);
void SD_SetBlockLen(U16 BlockSize);
bit STORAGE_Detect();
U8 SD_SetInterface(U8 tc_CurrCard);
U8 SDIdentification(U8 tc_CurrCard);
U8 SDToRespond(U8 *tc_RespBuff,U8 tc_RespType, U8 tc_CRC);
U8 SDCheckDat0(void);
U8 SD_SetBusWidth(U8 tc_BusMode);
U8 SD_Initializes(U8 tc_CurrCard);
U8 SD_StandByToTrans(void);
U8 SD_STORAGE_Initialize(void);
U8 SD_Read_LogicSector (U32 tdw_LogicSectorAddr,U32 tdw_ReadSectorNumber);
U8 SD_Write_LogicSector(U32 tdw_LogicSectorAddr,U32 tdw_WriteSectorNumber);
U8 UsbReadWaitSD(U8 tc_ReadOrWrite);
U8 UsbReadWaitBank1USB(U8 tc_ReadOrWrite);
extern U8 USER_READSAR(U8 tc_SARChannel);
void SD_SetClock(U8 ClockValue)
{
// 0=24M 1=12M 2=6M 3=375K
U8 tmp;
tmp = XBYTE[REG_SD_TIMER];
tmp = (tmp&0xfc)|(ClockValue&0x03);
XBYTE[REG_SD_TIMER]=tmp;
}
void SdDetect(void)
{
U8 tc_Loop;
U32 tdw_Bitcompare;
tdw_Bitcompare = 0x80000000;
for (tc_Loop = 0; tc_Loop < 32; tc_Loop ++)
{
if (gdw_CARD_TotalSizeMB & tdw_Bitcompare)
{
if ((gdw_CARD_TotalSizeMB & (~tdw_Bitcompare)) == 0)
{
gdw_CARD_TotalSizeMB = tdw_Bitcompare;
}
else
{
gdw_CARD_TotalSizeMB = tdw_Bitcompare << 1;
}
}
tdw_Bitcompare >>= 1;
}
}
U8 SD_SetInterface(U8 tc_CurrCard)
{
FlashExchang(tc_CurrCard,gc_CurrentCard,1);
XBYTE[REG_WAITRSPTIME] = 0xff;//REG_WAITRSPTIME = 0xB457
XBYTE[REG_WAITCRCTIME] = 0x08;//REG_WAITCRCTIME = 0xB458
if(tc_CurrCard==CURRENT_MEDIA_SD)
{
XBYTE[REG_SD_TIMER] = 0x30; //set sd card mode
}
else if(tc_CurrCard==CURRENT_MEDIA_MMC)
{
XBYTE[REG_SD_TIMER] = 0x70; //set mmc card mode
}
XBYTE[0xB451]&=0xf7;
SD_SetClock(3);
XBYTE[REG_SD_TIMER]&=0xfb;//set the clock frequency 6MHZ
SD_SetBlockLen(C_BLOCKSIZE);//C_BLOCKSIZE = 512
if(SDIdentification(tc_CurrCard))
{//not insert
if(SDIdentification(tc_CurrCard))
{
gc_ReadWriteTimeOut = 0;
return 1;
}
}
gc_ReadWriteTimeOut = 0;
return 0;
}
U8 SDIdentification(U8 tc_CurrCard)
{
U8 tc_ComBuff[5],tc_RespBuff[17];
U8 tc_Ture,tc_i;
U8 tc_ReadBl_Len;
U16 tw_BlockLen;
U16 tw_Mult;
U32 tw_CSize;
U8 tc_CSizeMult;
U32 tdw_CardTotalSize;
// Tx 100 clock for power on sequence
for(tc_i=0; tc_i<100; tc_i++)
{
SdTxDummy();
}
SDHC=0;
// CMD0
tc_ComBuff[0]=0x40;
tc_ComBuff[1]=0x00;
tc_ComBuff[2]=0x00;
tc_ComBuff[3]=0x00;
tc_ComBuff[4]=0x00;
CommandToSd(tc_ComBuff);
// 8 dummy clock
SdTxDummy();
if(tc_CurrCard==CURRENT_MEDIA_SD)
{
// CMD8
tc_ComBuff[0]=0x48;
tc_ComBuff[1]=0x00;
tc_ComBuff[2]=0x00;
tc_ComBuff[3]=0x01;
tc_ComBuff[4]=0x17;
CommandToSd(tc_ComBuff);
tc_Ture=SDToRespond(tc_RespBuff,C_48BitRsp,0);
if((tc_Ture==0)&&(tc_RespBuff[0]==0x08)&&(tc_RespBuff[4]==0x17))
{
SDHC=1;
}
// CMD55
while(1)
{
tc_ComBuff[0]=0x77;
tc_ComBuff[1]=0x00;
tc_ComBuff[2]=0x00;
tc_ComBuff[3]=0x00;
tc_ComBuff[4]=0x00;
CommandToSd(tc_ComBuff);
tc_Ture=SDToRespond(tc_RespBuff,C_48BitRsp,0);
if((tc_Ture)||(tc_RespBuff[0]!=0x37))
{
return 1;
}
// ACMD41
tc_ComBuff[0]=0x69;
if(SDHC==1)
{
tc_ComBuff[1]=0x40;
tc_ComBuff[2]=0xFF;
tc_ComBuff[3]=0x80;
tc_ComBuff[4]=0x00;
}
else
{
tc_ComBuff[1]=0x00;
tc_ComBuff[2]=0x04;
tc_ComBuff[3]=0x00;
tc_ComBuff[4]=0x00;
}
CommandToSd(tc_ComBuff);
tc_Ture=SDToRespond(tc_RespBuff,C_48BitRsp,0);
//检查回应是否有错误
if((tc_Ture)||(tc_RespBuff[0]!=0x3f))
{
return 1;
}
if(tc_RespBuff[1]&0x80)
{
if((tc_RespBuff[1]&0x40)==0) // SD 2.0 standard capacity, maxliao 20071224
{
SDHC=0;
}
break;
}
}
gc_SD_RCA[0]=0;
gc_SD_RCA[1]=0;
}
else if(tc_CurrCard==CURRENT_MEDIA_MMC)
{
SDHC=0;
//send cmd1 to make mmc to ready state
do{
tc_ComBuff[0]=0x41;
tc_ComBuff[1]=0x00;
tc_ComBuff[2]=0x04;
tc_ComBuff[3]=0x00;
tc_ComBuff[4]=0x00;
CommandToSd(tc_ComBuff);
tc_Ture=SDToRespond(tc_RespBuff,C_48BitRsp,C_NotCrcCheck);
//检查回应是否有错误
if((tc_Ture)||(tc_RespBuff[0]!=0x3f))
{
return 1;
}
//等待card的power up status bit
}while((tc_RespBuff[1]&0x80)==0);
gc_SD_RCA[0]=0x55;
gc_SD_RCA[1]=0xaa;
}
for(tc_i=0; tc_i<4; tc_i++)
{
gc_SD_OCR[tc_i] = tc_RespBuff[tc_i+1];
}
// CMD2
tc_ComBuff[0]=0x42;
tc_ComBuff[1]=0x00;
tc_ComBuff[2]=0x00;
tc_ComBuff[3]=0x00;
tc_ComBuff[4]=0x00;
CommandToSd(tc_ComBuff);
tc_Ture=SDToRespond(tc_RespBuff,C_136BitRsp,C_NotCrcCheck);
if((tc_Ture)||(tc_RespBuff[0]!=0x3f))
{
return 1;
}
for(tc_i=0; tc_i<16; tc_i++)
{
gc_SD_CID[tc_i] = tc_RespBuff[tc_i+1];
}
// CMD3
tc_ComBuff[0]=0x43;
tc_ComBuff[1]=gc_SD_RCA[0];
tc_ComBuff[2]=gc_SD_RCA[1];
tc_ComBuff[3]=0x00;
tc_ComBuff[4]=0x00;
CommandToSd(tc_ComBuff);
tc_Ture=SDToRespond(tc_RespBuff,C_48BitRsp,C_NeedCrcCheck);
if((tc_Ture)||(tc_RespBuff[0]!=0x03))
{
return 1;
}
if(tc_CurrCard==CURRENT_MEDIA_SD)
{
gc_SD_RCA[0]=tc_RespBuff[1];
gc_SD_RCA[1]=tc_RespBuff[2];
}
// CMD9
tc_ComBuff[0] = 0x49;
tc_ComBuff[1] = gc_SD_RCA[0];
tc_ComBuff[2] = gc_SD_RCA[1];
tc_ComBuff[3] = 0x00;
tc_ComBuff[4] = 0x00;
CommandToSd(tc_ComBuff);
tc_Ture=SDToRespond(tc_RespBuff,C_136BitRsp,C_NotCrcCheck);
if((tc_Ture)||(tc_RespBuff[0]!=0x3f))
{
return 1;
}
for(tc_i=0; tc_i<16; tc_i++)
{
gc_SD_CSD[tc_i]=tc_RespBuff[tc_i+1];
}
tc_ReadBl_Len=gc_SD_CSD[5]&0x0f;
tw_BlockLen=0x01<< tc_ReadBl_Len;
gw_SD_BlockSize = tw_BlockLen;
if(SDHC==1)
{
tw_CSize=(((U32)gc_SD_CSD[7])<<16)|((U32)gc_SD_CSD[8]<<8)|((U32)gc_SD_CSD[9]);
gw_SD_BlockNum = (tw_CSize+1)*1024;
}
else
{
tw_CSize = (((U16)gc_SD_CSD[6]) << 10) | ((U16)gc_SD_CSD[7] << 2) | ((U16)gc_SD_CSD[8] >> 6);
tc_CSizeMult=((gc_SD_CSD[9] & 0x03) << 1) | (gc_SD_CSD[10] >> 7);
tw_Mult = 0x0001 << (tc_CSizeMult + 2);
gw_SD_BlockNum = (U32)(tw_CSize + 1) * (U32)tw_Mult; //get block num
}
tdw_CardTotalSize = gw_SD_BlockNum*(U32)tw_BlockLen;
gdw_DOS_SectorPerCard = tdw_CardTotalSize/512;
gdw_CARD_TotalSizeMB = tdw_CardTotalSize>>20;
SdDetect();//将容量转换成整数
SD_SetClock(1);
return 0;
}
U8 SDToRespond(U8 *tc_RespBuff,U8 tc_RespType, U8 tc_CRC)
{
U8 tc_FullFlag,tc_CRC7;
U8 tc_i;
if(tc_RespType == C_48BitRsp)
{
XBYTE[REG_SD_TIMER]&=0xf7;
}
else
{
XBYTE[REG_SD_TIMER]|=0x08;
}
XBYTE[REG_WAITRSPTIME]=0xff;
XBYTE[REG_SD_TRIGGER]|=C_bit_RxRsp;
do
{
tc_FullFlag=(XBYTE[REG_SD_STATE0]&0x02);
}while((tc_FullFlag==0)&&((XBYTE[REG_SD_STATE0]&0x40)==0));
if((tc_FullFlag==0)&&((XBYTE[REG_SD_STATE0]&0x40)))
{
XBYTE[0xB450] = 0x03;//reset SD interface
gc_ReadWriteTimeOut = 1;
return 0x01;
}
if (tc_RespType == C_48BitRsp)
{
//send 8 dummy clock
SdTxDummy();
{
U16 tw_TimeOut;
tw_TimeOut = K_CARD_TIMEOUTSECONDS;
while ((XBYTE[REG_SD_STATE1] & 0x0F) != 0x00) //wait the card into idle
{
tw_TimeOut --;
if (gc_SysCardInsert)
{//if CD pin is HIGH,the C
tw_TimeOut = 0;
}
if (!tw_TimeOut)
{
XBYTE[0xB450] = 0x03;//reset SD