📄 sdi2410.c
字号:
int err, try;
int i, start, end;
if (sector == 0xFFFFFFFF)
{
start = 0; end = SDCARD_BUFFER_BLOCK_MAX;
}
else
{
S_DWORD cluster = (sector+sdcard.part[0].RelativeSec)/(sdcard.BlockLen/SDCARD_FAT_SECTOR_BYTES);
for (i = 0; i < SDCARD_BUFFER_BLOCK_MAX; i++)
if (SDCARDClst[i] == cluster)
break;
if (i == SDCARD_BUFFER_BLOCK_MAX)
start = 0, end = 0;
else
start = i, end = i+1;
}
for (i = start; i < end; i++)
{
if ((SDCARDFlag[i]&SDCARD_BUFFER_NEEDFLUSH) == SDCARD_BUFFER_NEEDFLUSH)
{
try = 3;
do
{
err = sdi_WriteBlock(SDCARDClst[i], SDCARDBuf[i]);
}while (err && try--);
if (err)
return err;
SDCARDFlag[i] &= ~SDCARD_BUFFER_NEEDFLUSH;
}
if (FreeBuffer)
{
SDCARDFlag[i] = 0x00;
SDCARDClst[i] = 0xFFFFFFFF;
}
}
return 0;
}
//sub function define
//
static int sdi_SDcardInit(void)
{
int err;
// Important notice for MMC test condition
// Cmd & Data lines must be enabled pull up register
hai_memset(&sdcard, 0x00, sizeof(sdcard));
rSDIPRE = PCLK/(2*SDI_INITIALCLK)-1; // 400KHz
rSDICON = (1<<4)|(1<<1)|1; // Type B, FIFO reset, clk enable
rSDIBSIZE = 0x200; // 512byte(128word)
rSDIDTIMER = 0xffff; // Set timeout count
for(err = 0; err < 0x1000; err++); // Wait 74SDCLK for MMC card
//CMD0: make idle
if (err = sdi_SendCmd(SDICMD_GO_IDLE_STATE, 0))
return err;
//MMC=>CMD1;SD=>ACMD41: make ready
if (!(err = sdi_ChkMMCOCR()))
sdcard.CardType = SDT_MMC_CARD;
else if (!(err = sdi_ChkSDOCR()))
sdcard.CardType = SDT_SD_CARD;
else
return err;
//CMD2: make identification
if (err = sdi_MakeIdent())
return err;
//CMD3: make stand by
if (sdcard.CardType == SDT_MMC_CARD)
sdcard.RCA = 1;
if (err = sdi_MakeStandby(&sdcard.RCA))//CMD3(MMC:Set RCA, SD:Ask RCA)
return err;
if (err = sdi_GetCID(sdcard.RCA, &sdcard.CID))
return err;
if (err = sdi_GetCSD(sdcard.RCA, &sdcard.CSD))
return err;
//normal clock
rSDIPRE = PCLK/(2*SDI_NORMALCLK)-1;
//CMD7: make transfer
if (err = sdi_CardSelect(sdcard.RCA))
return err;
//ACMD6: set bus width
if (sdcard.CardType != SDT_MMC_CARD)
{
sdcard.flag |= SD_BUSW_4BIT;
if (err = sdi_SetBusWidth(sdcard.RCA, (sdcard.flag&SD_BUSW_MASK)?1:0))
return err;
}
return 0;
}
static int sdi_SendCmd(int rCMD, int rARG)
{
int state, err = -1;
rSDICARG = rARG;
rSDICCON = rCMD|SDICMD_START|SDICMD_HOST;
if(rCMD&SDICMD_WTRSP)
{
do
{
state = rSDICSTA;
}while(!((state&0x200)||(state&0x400))); // Check cmd/rsp end
if((rCMD&SDICMD_IDXMSK)==1 || (rCMD&SDICMD_IDXMSK)==9 || (rCMD&SDICMD_IDXMSK)==41) // CRC no check
{
if((state&0xf00) != 0xa00)
{
if((state&0x400)==0x400)
err = -1; // Timeout error
}
}
else
{
if((state&0x1f00) != 0xa00)
{
if((state&0x400)==0x400)
err = -1; // Timeout error
else
err = -2; // crc fail
}
}
}
else
{
do
{
state = rSDICSTA;
}while((state&0x800)!=0x800); // Check cmd end
}
rSDICSTA = state;// Clear cmd end state
return err;
}
static int sdi_CMD55(S_WORD RCA)
{
return sdi_SendCmd(SDICMD_WTRSP|SDICMD_APP_CMD, (int)RCA<<16);
}
static int sdi_ChkMMCOCR(void)
{
int try;
for(try = 0; try < 9; try++)
{
//0xffc000:(OCR:2.6V~3.6V)
if (!sdi_SendCmd(SDICMD_S_RSP|SDICMD_WTRSP|SDICMD_OP_COND, 0xffc000))
{
if(rSDIRSP0 == 0x80ffc000)
return 0; // Success
}
}
return -1;
}
static int sdi_ChkSDOCR(void)
{
int try, delay;
for(try = 0; try < 9; try++)
{
if (sdi_CMD55(0)) // Make ACMD
continue;
//0xff8000 : (OCR:2.7V~3.6V)
if (!sdi_SendCmd(SDICMD_S_RSP|SDICMD_WTRSP|SDICMD_SD_APP_OP_COND, 0xff8000))
{
if(rSDIRSP0 == 0x80ff8000)
return 0; // Success
}
for(delay = 0; delay < 1000; delay++); // Wait Card power up status
}
return -1;
}
static int sdi_MakeIdent(void)
{
int err, try = 3;
do
{
err = sdi_SendCmd(SDICMD_L_RSP|SDICMD_WTRSP|SDICMD_ALL_SEND_CID, 0);
}while(err && try--);
return err;
}
static int sdi_MakeStandby(S_WORD *pRCA)
{
int err, try = 3, arg = (int)*pRCA;
do
{// CMD3(MMC:Set RCA, SD:Ask RCA-->SBZ)
err = sdi_SendCmd(SDICMD_WTRSP|SDICMD_SEND_REL_ADDR, arg<<16);
}while (err && try--);
if (err)
return err;
if (*pRCA)//MMC
;
else
*pRCA = (rSDIRSP0&0xFFFF0000)>>16;
if (rSDIRSP0&0x1e00 != 0x600) //check if enter stand-by
err = -1;
return err;
}
static int sdi_GetCID(S_WORD RCA, SP_CID pCID)
{
int err, try = 3, val;
S_BYTE rsp[16];
do
{
err = sdi_SendCmd(SDICMD_L_RSP|SDICMD_WTRSP|SDICMD_SEND_CID, (int)RCA<<16);
}while(err && try--);
if (err) return err;
val = rSDIRSP0; HAI_WRITEDWORD(rsp+12, val);
val = rSDIRSP1; HAI_WRITEDWORD(rsp+ 8, val);
val = rSDIRSP2; HAI_WRITEDWORD(rsp+ 4, val);
val = rSDIRSP3; HAI_WRITEDWORD(rsp+ 0, val);
pCID->MID = rsp[15];
pCID->OID[1] = rsp[14];
pCID->OID[0] = rsp[13];
pCID->PNM[4] = rsp[12];
pCID->PNM[3] = rsp[11];
pCID->PNM[2] = rsp[10];
pCID->PNM[1] = rsp[ 9];
pCID->PNM[0] = rsp[ 8];
pCID->PRV = rsp[ 7];
pCID->PSN[3] = rsp[ 6];
pCID->PSN[2] = rsp[ 5];
pCID->PSN[1] = rsp[ 4];
pCID->PSN[0] = rsp[ 3];
pCID->MDT[1] = rsp[ 2]&0x0F;
pCID->MDT[0] = rsp[ 1];
return err;
}
static int sdi_GetCSD(S_WORD RCA, SP_CSD pCSD)
{
int err, try = 3, val;
S_BYTE rsp[16];
do
{
err = sdi_SendCmd(SDICMD_L_RSP|SDICMD_WTRSP|SDICMD_SEND_CSD, (int)RCA<<16);
}while(err && try--);
if (err) return err;
val = rSDIRSP0; HAI_WRITEDWORD(rsp+12, val);
val = rSDIRSP1; HAI_WRITEDWORD(rsp+ 8, val);
val = rSDIRSP2; HAI_WRITEDWORD(rsp+ 4, val);
val = rSDIRSP3; HAI_WRITEDWORD(rsp+ 0, val);
sdcard.BlockLen = 512;//temp
return err;
}
static int sdi_CardSelect(S_WORD RCA)
{
int err, try = 3;
do
{
err = sdi_SendCmd(SDICMD_WTRSP|SDICMD_SEL_DSEL_CARD, (int)RCA<<16);
}while (err && try--);
if(rSDIRSP0&0x1e00 != 0x800)
err = -1;
return err;
}
static int sdi_SetBusWidth(S_WORD RCA, int BUSW)
{
int err, try = 3;
do
{
if (err = sdi_CMD55(RCA))
continue;
err = sdi_SendCmd(SDICMD_WTRSP|SDICMD_SET_BUS_WIDTH, BUSW<<1);
}while (err && try--);
return err;
}
static int sdi_ReadBlock(S_DWORD block, S_BYTE *OutBuf)
{
int err, try = 3;
int *pOut = (int *)OutBuf;
int MaxRead = sdcard.BlockLen;
int BusW = (sdcard.flag&SD_BUSW_MASK)?1:0;
rSDICON |= (1<<1);// FIFO reset
rSDIDCON = (1<<19)|(1<<17)|(BusW<<16)|(2<<12)|(1<<0);// Rx after cmd, blk, 4bit bus, Rx start, blk num
do
{
err = sdi_SendCmd(SDICMD_WTRSP|SDICMD_READ_SINGLBLK, block);
}while (err && try--);
if (err) return err;
for (try = 0; try < MaxRead; )
{
if((rSDIDSTA&0x20) == 0x20)
{
rSDIDSTA = 0x20;
break;
}
err = rSDIFSTA;
if((err&0x1000) == 0x1000)
{
*pOut++ = rSDIDAT;
try += 4;
}
}
err = sdi_CheckDATend();
rSDIDSTA = 0x10;// Clear data Tx/Rx end
return err;
}
static int sdi_WriteBlock(S_DWORD block, S_BYTE *InBuf)
{
int err, try = 3;
int *pin = (int *)InBuf;
int MaxWrite = sdcard.BlockLen;
int BusW = (sdcard.flag&SD_BUSW_MASK)?1:0;
rSDICON |= (1<<1);// FIFO reset
rSDIDCON = (1<<20)|(1<<17)|(BusW<<16)|(3<<12)|(1<<0);// Tx after rsp, blk, 4bit bus, Tx start, blk num
do
{
err = sdi_SendCmd(SDICMD_WTRSP|SDICMD_WRITE_SINGLBLK, block);
}while (err && try--);
for (try = 0; try < MaxWrite; )
{
err = rSDIFSTA;
if((err&0x2000) == 0x2000)
{
rSDIDAT = *pin++;
try += 4;
}
}
err = sdi_CheckDATend();
rSDIDSTA = 0x10;// Clear data Tx/Rx end
return err;
}
static int sdi_CheckDATend(void)
{
int finish;
do
{
finish = rSDIDSTA;
}while(!(finish&0x30));// Chek timeout or data end
if((finish&0xfc) != 0x10)
{
rSDIDSTA = 0xec;// Clear error state
return -1;
}
return 0;
}
static void sdi_IncUseCount(int BufNo)
{
S_DWORD UseCnt = SDCARDFlag[BufNo]&0x0000FFFF;
UseCnt = (UseCnt<0xFFFF)? (UseCnt+1):(UseCnt);//increase use count
SDCARDFlag[BufNo] = (SDCARDFlag[BufNo]&0xFFFF0000)|(UseCnt&0x0000FFFF);
}
static int sdi_FindLeastUseCluster(void)
{
int i = 0, m = 0;
S_DWORD UseCnt = SDCARDFlag[i]&0x0000FFFF;
for (i = 1; i < SDCARD_BUFFER_BLOCK_MAX; i++)
{
if (UseCnt > (SDCARDFlag[i]&0x0000FFFF))
{
UseCnt = SDCARDFlag[i]&0x0000FFFF;
m = i;
}
}
return m;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -