📄 sd.c
字号:
#include "fs7805.h"
#include "fs7805regs.h"
#include "sd.h"
#include "include.h"
static INT32U xdata SdAvailableBlocks = 0;
static TCARD_TYPE xdata CardType = CARD_SD;
BYTE idata SdCmdBuf[5];
BYTE xdata SdRespBuf[17];
BYTE xdata SdRespBufForProgCsd[17];
static INT32U idata RCA = 0;
static BOOL MmcProtol;
INT32U SectorStart = 0;
INT16U SectorCount = 0;
BYTE CmdTimer;
void SdInit()
{
SYSIO_CFG=SYSIO_CFG|bmSD_EN; //enable SDMI interface
SDMI_CTL&=~bmSD_AUTO_CLK_EN; //
SDMI_CTL |= bmSD_CLK_40;//
}
void SdLowClk()
{
SDMI_CTL=(SDMI_CTL&~bmSD_CLK_SEL)|bmSD_CLK_EN;
}
void SdHiClk()
{
SDMI_CTL=(SDMI_CTL|bmSD_CLK_SEL)|bmSD_CLK_EN;
}
void SdStopClk()
{
SDMI_CTL=SDMI_CTL & ~bmSD_CLK_EN & ~bmSD_AUTO_CLK_EN;
}
void SdWaitCard()
{
while(SDMI_ST&bmSD_BUSY);
}
BYTE SdGetRespType(BYTE CmdIndex)
{
if(CmdIndex == SEND_RELATIVE_ADDR)
{
//if(CardType == CARD_SD)
return TYPE_RESP_R6;
//else
// return TYPE_RESP_R1;
}
switch(CmdIndex)
{
case GO_IDLE_STATE : return TYPE_RESP_NO; break;
case SEND_OP_COND : return TYPE_RESP_R3; break;
case ALL_SEND_CID : return TYPE_RESP_R2; break;
case SET_DSR : return TYPE_RESP_NO; break;
case SWITCH : return TYPE_RESP_R1; break;
case SELECT_CARD : return TYPE_RESP_R1; break;
case SEND_EXT_CSD : return TYPE_RESP_R1; break;
case SEND_CSD : return TYPE_RESP_R2; break;
case SEND_CID : return TYPE_RESP_R2; break;
case READ_DAT_UNTIL_STOP : return TYPE_RESP_R1; break;
case STOP_TRANS : return TYPE_RESP_R1; break;
case SEND_STATUS : return TYPE_RESP_R1; break;
case GO_INACTIVE_STATE : return TYPE_RESP_NO; break;
case SET_BLOCK_LEN : return TYPE_RESP_R1; break;
case READ_BLOCK : return TYPE_RESP_R1; break;
case READ_MUL_BLOCK : return TYPE_RESP_R1; break;
case WRITE_DAT_UNTIL_STOP : return TYPE_RESP_R1; break;
case SET_BLOCK_COUNT : return TYPE_RESP_R1; break;
case WRITE_BLOCK : return TYPE_RESP_R1; break;
case WRITE_MUL_BLOCK : return TYPE_RESP_R1; break;
case PROGRAM_CID : return TYPE_RESP_R1; break;
case PROGRAM_CSD : return TYPE_RESP_R1; break;
case SET_WRITE_PROT : return TYPE_RESP_R1; break;
case CLR_WRITE_PROT : return TYPE_RESP_R1; break;
case SEND_WRITE_PROT : return TYPE_RESP_R1; break;
case ERASE_WR_BLK_START : return TYPE_RESP_R1; break;
case ERASE_WR_BLK_END : return TYPE_RESP_R1; break;
case ERASE_GROUP_START : return TYPE_RESP_R1; break;
case ERASE_GROUP_END : return TYPE_RESP_R1; break;
case ERASE : return TYPE_RESP_R1; break;
case FAST_IO : return TYPE_RESP_R4; break;
case GO_IRQ_STATE : return TYPE_RESP_R5; break;
case LOCK_UNLOCK : return TYPE_RESP_R1; break;
case APP_CMD : return TYPE_RESP_R1; break;
case GEN_CMD : return TYPE_RESP_R1; break;
// APP_CMDs
case SEND_NUM_WR_BLOCKS : return TYPE_RESP_R1; break;
case SD_SEND_OP_COND : return TYPE_RESP_R3; break;
case SEND_SCR : return TYPE_RESP_R1; break;
default : return TYPE_RESP_NO; break;
}
// Following commands are with identical index and response type:
// 1. SET_BUS_WIDTH (ACMD6) Response R1
// SWITCH (CMD6) Response R1
// 2. SEND_SD_STATUS (ACMD13) Response R1
// SEND_STATUS (CMD13) Response R1
// 3. SET_WR_BLK_ERASE_CNT (ACMD23) Response R1
// SET_BLOCK_COUNT (CMD23) Response R1
// 4. SET_CLR_CARD_DETECT (ACMD42) Response R1
// LOCK_UNLOCK (CMD42) Response R1
}
STATUS SdSendCmd(BYTE CmdIndex, BYTE *CmdBuf)
{
BYTE RespType , RespLen , CmdType;
BYTE i;
BYTE RetryCount = 0;
RespType = SdGetRespType(CmdIndex);
if( (CmdIndex == GEN_CMD)||
(CmdIndex == SEND_NUM_WR_BLOCKS)||
(CmdIndex == SEND_SCR)||
(CmdIndex == SEND_EXT_CSD)||
(CmdIndex == READ_BLOCK)||
(CmdIndex == READ_MUL_BLOCK)||
(CmdIndex == READ_DAT_UNTIL_STOP)/*||
(CmdIndex == SEND_WRITE_PROT)*/) //2006.05.21
{
RespLen = 6;
CmdType = SD_CMD_RX_DATA;
}
else if((CmdIndex == PROGRAM_CSD)||
(CmdIndex == LOCK_UNLOCK)||
(CmdIndex == WRITE_BLOCK)||
(CmdIndex == WRITE_MUL_BLOCK))
{
RespLen = 6;
CmdType = SD_CMD_TX_DATA;
}
else if(RespType == TYPE_RESP_NO)
{
RespLen = 0;
CmdType = SD_CMD_ONLY;
}
else if(RespType == TYPE_RESP_R2)
{
RespLen = 17;
CmdType = SD_CMD_LONG_RSP;
}
else
{
RespLen = 6;
CmdType = SD_CMD_SHORT_RSP;
}
if (CmdIndex == 0x5)
{
RespLen = 6;
CmdType = SD_CMD_SHORT_RSP;
}
for( ; RetryCount < 3; RetryCount++)
{
SDMCMDRESBUF00=0x40|CmdIndex; //The First byte
for(i = 1; i <= 4; i++) //The next 4 bytes
((BYTE xdata *)(&SDMCMDRESBUF00))[i]=CmdBuf[i];
SDMI_CMD=CmdType;
CmdTimer = 5; // 50ms
//while((SDMI_INT&bmSD_COMPLETE_INT)==0);
//SDMI_INT&=~bmSD_COMPLETE_INT;
while(CmdTimer > 0)
{
if((SDMI_INT&bmSD_COMPLETE_INT)!=0) //wait for command is completed.
{
SDMI_INT&=~bmSD_COMPLETE_INT;
break;
}
}//*/
if(CmdTimer == 0) // Timeout
{
SdCtrlReset(); // ???
//MMCerror2++;
continue;
}
if(RespType == TYPE_RESP_NO)
return STATUS_SUCCESS;
if(RespType == TYPE_RESP_R3)
{
// The response type of SD_SEND_OP_COND (ACMD41) and
// SEND_OP_COND (CMD1) are both R3, which is not protected
// by CRC7. But hardware could still report CRC7 error for
// these command's response. So, to prevent from affecting
// next command, we clear CRC7-ERR INT bit here.
SDMI_ST&=~bmSD_CRC7_ERR;
for(i = 0; i < RespLen; i++)
SdRespBuf[i] = ((BYTE xdata *)(&SDMCMDRESBUF00))[i];
return STATUS_SUCCESS;
}
if(SDMI_ST&bmSD_CRC7_ERR) // CRC7 Error
{
SDMI_ST&=~bmSD_CRC7_ERR; // Clear INT
continue;
}
for(i = 0; i < RespLen; i++)
SdRespBuf[i] = ((BYTE xdata *)(&SDMCMDRESBUF00))[i];
if(RespType == TYPE_RESP_R1)
{
// Check following error bits in Card Status:
// 31 OUT_OF_RANGE SdRespBuf[1].7
// 30 ADDRESS_ERROR SdRespBuf[1].6
// 29 BLOCK_LEN_ERROR SdRespBuf[1].5
// 28 ERASE_SEQ_ERROR SdRespBuf[1].4
// 27 ERASE_PARAM SdRespBuf[1].3
// 26 WP_VIOLATION SdRespBuf[1].2
// 24 LOCK_UNLOCK_FAILED SdRespBuf[1].0
// 23 COM_CRC_ERR SdRespBuf[2].7
// 22 ILLEGAL_COMMAND SdRespBuf[2].6
// 21 CARD_ECC_FAILED SdRespBuf[2].5
// 20 CC_ERROR SdRespBuf[2].4
// 19 ERROR SdRespBuf[2].3
if( ( (SdRespBuf[1] & 0xFD) == 0 ) && // 8'b1111_1101
( (SdRespBuf[2] & 0xF8) == 0 ) ) // 8'b1111_1000
return STATUS_SUCCESS; // No error
else
if( ( SdRespBuf[1] == 0x80 ) && //ignor OUT_OF_RANGE error
( SdRespBuf[2] == 0 ) && // when multi read last 5 blocks
(( SectorStart >= SdAvailableBlocks-5)||
( SectorStart <= SdAvailableBlocks))) //see MMC 4.0 SPEC--4.6.3(page 49)
return STATUS_SUCCESS; //
else //
continue;
}
else
return STATUS_SUCCESS;
}
return STATUS_FLASH_ERROR;
}
STATUS SdSendAppCmd(BYTE AppCmdIndex, BYTE *CmdBuf)
{
STATUS Status;
int RetryCount;
BYTE CmdBuf55[5]; // for APP_CMD (CMD55)
for(RetryCount = 0; RetryCount < 3; RetryCount++)
{
*((INT32U *)(&CmdBuf55[1])) = RCA;
Status = SdSendCmd(APP_CMD,CmdBuf55);
if(Status != STATUS_SUCCESS)
{
continue;
}
Status = SdSendCmd(AppCmdIndex,CmdBuf);
if(Status != STATUS_SUCCESS)
continue;
else
return STATUS_SUCCESS;
}
return STATUS_FLASH_ERROR;
}
STATUS SdReset()
{
STATUS Status;
int i;
SdLowClk();
Delay1ms(150);
for(i = 1; i <= 4; i++)
SdCmdBuf[i]=0;
Status = SdSendCmd(GO_IDLE_STATE,SdCmdBuf);
return Status;
}
STATUS SdCardDetect()
{
STATUS Status;
INT16U RetryCount;
*(INT32U *)(&SdCmdBuf[1])=OPERATION_VOL_RANGE;
Status = SdSendAppCmd(SD_SEND_OP_COND, SdCmdBuf);
if(Status == STATUS_SUCCESS)
{
CardType = CARD_SD;
// Check if card power-up operation finished
if(SDMCMDRESBUF01 & CARD_PWRUP_FINISH)
return STATUS_SUCCESS;
// Wait until card power-up operation finished
for(RetryCount = 0; RetryCount < 500; RetryCount++)
{
*((INT32U idata *)(&SdCmdBuf[1])) = OPERATION_VOL_RANGE;
Status = SdSendAppCmd(SD_SEND_OP_COND, SdCmdBuf);
if(Status != STATUS_SUCCESS)
continue;
if(SDMCMDRESBUF01 & CARD_PWRUP_FINISH)
return STATUS_SUCCESS;
}
return STATUS_FLASH_ERROR;
}
else
{
CardType = CARD_MMC;
// Wait until card power-up operation finished
for(RetryCount = 0; RetryCount < 500; RetryCount++)
{
*((INT32U *)(&SdCmdBuf[1])) = OPERATION_VOL_RANGE;
Status = SdSendCmd(SEND_OP_COND, SdCmdBuf);
if(Status != STATUS_SUCCESS)
continue;
if(SdRespBuf[1] & CARD_PWRUP_FINISH)
return STATUS_SUCCESS;
}
return STATUS_FLASH_ERROR;
}
return Status;
}
STATUS SdGoIdentifyState()
{
STATUS Status;
int i;
for(i = 1; i <= 4; i++)
SdCmdBuf[i] = 0;
Status = SdSendCmd(ALL_SEND_CID,SdCmdBuf);
return Status;
}
STATUS SdGoStandbyState()
{
STATUS Status;
int i;
if(CardType == CARD_SD)
{
for(i = 1; i <= 4; i++)
SdCmdBuf[i] = 0;
}
else
{
RCA = 0x00010000;
*((INT32U idata *)(&SdCmdBuf[1])) = RCA;
}
Status = SdSendCmd(SEND_RELATIVE_ADDR,SdCmdBuf);
if(CardType == CARD_SD)
RCA = *((INT32U *)(&SdRespBuf[1])) & 0xffff0000;
return STATUS_SUCCESS;
}
//--------------------------------------------------------------------
STATUS SdReadCSD()
{
STATUS Status;
BYTE READ_BL_LEN;
BYTE C_SIZE_MUTI;
INT32U C_SIZE;
int i;
*((INT32U *)(&SdCmdBuf[1])) = RCA;
Status = SdSendCmd(SEND_CSD,SdCmdBuf);
for(i=0;i<17;i++)
SdRespBufForProgCsd[i]=SdRespBuf[i];
if(Status != STATUS_SUCCESS)
return Status;
if(SdRespBuf[1] & 0x3c)//check MMC3.1 or MMC4.0
MmcProtol = TRUE;
else
MmcProtol = FALSE;
READ_BL_LEN = SdRespBuf[6] & 0xf;
C_SIZE = SdRespBuf[7] & 0x3;
C_SIZE <<= 8;
C_SIZE |= SdRespBuf[8];
C_SIZE <<= 2;
C_SIZE |= (SdRespBuf[9] >> 6);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -