📄 sd.c
字号:
}
#if defined(MSDC_SD_BITS4_BUS)
if((status = SD_SetBusWidth(BIT_4W))!=NO_ERROR)
{
goto err;
}
#endif
if((status = SD_Acmd42(KAL_FALSE))!=NO_ERROR)
{
goto err;
}
}
else
{
#if defined(MSDC_MMC40_SUPPORT)
if(gMSDC_Handle.mMSDC_type == MMC_CARD && gSD.mCSD.spec_ver >= 4)
{
gMSDC_Handle.mMSDC_type = MMC40_CARD;
if((status = SD_SetMMC40_bus_high_speed())!= NO_ERROR)
goto err;
}
else
#endif
{
MSDC_CLR_BIT32(MSDC_CFG, MSDC_CFG_CLKSRC);
gMSDC_Handle.msdc_clock = MSDC_CLOCK;
MSDC_SetClock(MSDC_OP_CLOCK);
}
}
// set block length (CMD16)
status = SD_SetBlength(512);
err:
if(status != NO_ERROR)
{
kal_print("SD mount fail!");
SD_SetDefault();
gMSDC_Handle.mIsInitialized = KAL_FALSE;
}
else
{
kal_print("SD mount ok!");
gMSDC_Handle.mIsInitialized = KAL_TRUE;
}
kal_set_eg_events(MSDC_Events, 0, KAL_AND);
return status ;
}
void SD_InvertN(kal_uint8 *dest, kal_uint8 *src, kal_uint8 len)
{
int i;
for(i=0; i<len; i++)
*(dest+len-1-i) = *(src+i);
}
/*************************************************************************
* FUNCTION
* power2
*
* DESCRIPTION
* Calculate the power of 2
*
* PARAMETERS
* num:
*
* RETURNS
* 2^num
*
* GLOBALS AFFECTED
*
*************************************************************************/
static kal_uint32 power2(kal_uint32 num)
{
return 1 << num;
}
/*************************************************************************
* FUNCTION
* SD_AnalysisCSD
*
* DESCRIPTION
* Analysis Card Specific Data and store in the member of gSD
*
* PARAMETERS
* csd: input csd for analysis
* RETURNS
*
* GLOBALS AFFECTED
* gSD
*
*************************************************************************/
void SD_AnalysisCSD(kal_uint32* csd)
{
kal_uint8 *ptr;
kal_uint32 c_mult,c_size;
ptr = (kal_uint8*)csd;
c_mult = c_size = 0;
// these offsets refer to the spec. of SD and MMC
GetBitFieldN((kal_uint8*)&gSD.mCSD.csd_ver, ptr, 126,2);
GetBitFieldN((kal_uint8*)&gSD.mCSD.tacc,ptr,112,8);
GetBitFieldN((kal_uint8*)&gSD.mCSD.nsac,ptr,104,8);
GetBitFieldN((kal_uint8*)&gSD.mCSD.tran_speed,ptr,96,8);
GetBitFieldN((kal_uint8*)&gSD.mCSD.ccc,ptr,84,12);
GetBitFieldN((kal_uint8*)&gSD.mCSD.r_blk_len,ptr,80,4);
gSD.mCSD.r_blk_len = power2(gSD.mCSD.r_blk_len);
GetBitFieldN((kal_uint8*)&gSD.mCSD.r_blk_part,ptr,79,1);
GetBitFieldN((kal_uint8*)&gSD.mCSD.w_blk_misali,ptr,78,1);
GetBitFieldN((kal_uint8*)&gSD.mCSD.r_blk_misali,ptr,77,1);
GetBitFieldN((kal_uint8*)&gSD.mCSD.dsr_imp,ptr,76,1);
GetBitFieldN((kal_uint8*)&gSD.mCSD.w_blk_part,ptr,21,1);
GetBitFieldN((kal_uint8*)&gSD.mCSD.w_blk_len,ptr,22,4);
gSD.mCSD.w_blk_len = power2(gSD.mCSD.w_blk_len);
GetBitFieldN((kal_uint8*)&gSD.mCSD.wp_grp_enable,ptr,31,1);
// there are some difference of CSD between SD and MMC
if(gMSDC_Handle.mMSDC_type == MMC_CARD)
{
GetBitFieldN((kal_uint8*)&gSD.mCSD.spec_ver, ptr, 122,4);
GetBitFieldN((kal_uint8*)&gSD.mCSD.erase_sec_size_mmc,ptr,42,5);
gSD.mCSD.erase_sec_size_mmc = (gSD.mCSD.erase_sec_size_mmc+1)*gSD.mCSD.w_blk_len;
GetBitFieldN((kal_uint8*)&gSD.mCSD.erase_grp_size_mmc,ptr,37,5);
gSD.mCSD.erase_grp_size_mmc = (gSD.mCSD.erase_grp_size_mmc+1)*gSD.mCSD.erase_sec_size_mmc;
GetBitFieldN((kal_uint8*)&gSD.mCSD.wp_grp_size_mmc,ptr,32,5);
gSD.mCSD.wp_grp_size_mmc = (gSD.mCSD.wp_grp_size_mmc + 1)*gSD.mCSD.erase_grp_size_mmc;
}
else // SD_CARD
{
GetBitFieldN((kal_uint8*)&gSD.mCSD.erase_sec_size_sd,ptr,39,7);
gSD.mCSD.erase_sec_size_sd += 1;
GetBitFieldN((kal_uint8*)&gSD.mCSD.wp_prg_size_sd,ptr,32,7);
gSD.mCSD.wp_prg_size_sd = (gSD.mCSD.wp_prg_size_sd+1) * gSD.mCSD.erase_sec_size_sd;
GetBitFieldN((kal_uint8*)&gSD.mCSD.erase_blk_en_sd,ptr,46,1);
}
GetBitFieldN((kal_uint8*)&c_mult,ptr,47,3);
c_mult = power2(c_mult+2);
GetBitFieldN((kal_uint8*)&c_size,ptr,62,12);
gSD.mBKNum = (c_size+1)*c_mult;
gSD.mCSD.capacity = (c_size+1)*c_mult*gSD.mCSD.r_blk_len;
}
/*************************************************************************
* FUNCTION
* SD_AnalysisCID
*
* DESCRIPTION
* Analysis Card Identificaton and store in the member of gSD
*
* PARAMETERS
* cid: input of card ID for analysis
* RETURNS
*
* GLOBALS AFFECTED
* gSD
*
*************************************************************************/
void SD_AnalysisCID(kal_uint32* cid)
{
kal_uint8 i;
kal_uint8* pcid;
pcid = (kal_uint8*)cid;
if(gMSDC_Handle.mMSDC_type == MMC_CARD)
{
GetBitFieldN((kal_uint8*)&gSD.mCID.year,pcid,8,4);
gSD.mCID.year += 1997;
GetBitFieldN((kal_uint8*)&gSD.mCID.month,pcid,12,4);
GetBitFieldN((kal_uint8*)&gSD.mCID.psn,pcid,16,32);
GetBitFieldN((kal_uint8*)&gSD.mCID.prv,pcid,48,8);
for(i=0;i<6;i++)
gSD.mCID.pnm[i] = *(pcid+7+i);
GetBitFieldN((kal_uint8*)&gSD.mCID.oid,pcid,104,16);
GetBitFieldN((kal_uint8*)&gSD.mCID.mid,pcid,120,8);
// special case handling
{
kal_uint8 pnm[] = {0xFF,0xFF,0xFF,0xFF,0x36,0x31};
if(gSD.mCID.mid == 6 && gSD.mCID.oid == 0 &&
!kal_mem_cmp(gSD.mCID.pnm,pnm,6))
{
gSD.flags |= SD_FLAG_MMC_MRSW_FAIL;
}
}
}
else // SD_CARD
{
gSD.mCID.mid = *(pcid+15);
gSD.mCID.oid = *(pcid+13) + 256*(*(pcid+14));
for(i=0;i<5;i++)
gSD.mCID.pnm[i] = *(pcid+8+i);
gSD.mCID.prv = *(pcid+7);
gSD.mCID.psn = *(kal_uint32*)(pcid+3);
gSD.mCID.month = (kal_uint8)GET_BIT(*(pcid+1),0,BIT_MASK_4);
gSD.mCID.year = GET_BIT(*(pcid+1),4,BIT_MASK_4)+16*GET_BIT(*(pcid+2),0,BIT_MASK_4) + 2000;
}
}
/*************************************************************************
* FUNCTION
* SD_AnalysisSCR
*
* DESCRIPTION
* Analysis SD Card Configuration Register and store in the member of gSD
*
* PARAMETERS
* scr: input of scr for analysis
* RETURNS
*
* GLOBALS AFFECTED
* gSD
*
* NOTE
* Only for SD card.
*
*************************************************************************/
void SD_AnalysisSCR(kal_uint32* scr)
{
kal_uint8 *pscr;
pscr = (kal_uint8*)scr;
gSD.mSCR.dat_after_erase = (kal_uint8)GET_BIT(*(pscr+1),7,BIT_MASK_1);
gSD.mSCR.security = (kal_uint8)GET_BIT(*(pscr+1),4,BIT_MASK_3);
gSD.mSCR.bus_width = (kal_uint8)GET_BIT(*(pscr+1),0,BIT_MASK_4);
}
/*************************************************************************
* FUNCTION
* SD_WaitCmdRdyOrTo
*
* DESCRIPTION
* Wait until command ready or timeout
*
* PARAMETERS
*
* RETURNS
* SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
* Interrupt driven and polling are both implemented
*
*************************************************************************/
SDC_CMD_STATUS SD_WaitCmdRdyOrTo(void)
{
MSDC_START_TIMER(MSDC_TIMEOUT_PERIOD_CMD);
#ifdef MSDC_USE_INT
{
kal_uint32 flags = 0;
kal_uint16 sdc_cmdsta = 0;
if(!gMSDC_Handle.mIsPresent)
return ERR_CARD_NOT_PRESENT;
kal_retrieve_eg_events(MSDC_Events,EVENT_SDCMDIRQ,KAL_AND_CONSUME,&flags,KAL_SUSPEND);
MSDC_STOP_TIMER();
sdc_cmdsta = *(volatile kal_uint16*)SDC_CMDSTA;
gMSDC_Handle.cmd_sta = sdc_cmdsta;
if(sdc_cmdsta & SDC_CMDSTA_CMDTO)
{
kal_prompt_trace(MOD_MSDC_HISR,"[MSDC]:cmd timeout");
return ERR_CMD_TIMEOUT;
}
else if(sdc_cmdsta & SDC_CMDSTA_RSPCRCERR)
{
kal_prompt_trace(MOD_MSDC_HISR,"[MSDC]:cmd crc");
return ERR_CMD_RSPCRCERR;
}
else if(sdc_cmdsta & SDC_CMDSTA_CMDRDY)
return NO_ERROR;
}
#else
{
volatile kal_uint16 sdc_cmdsta;
while(!(sdc_cmdsta = *(volatile kal_uint16*)SDC_CMDSTA)
&& MSDC_Check_Card_Present() && !gMSDC_Handle.is_timeout);
MSDC_STOP_TIMER();
MSDC_CLR_INT();
gMSDC_Handle.cmd_sta = sdc_cmdsta;
if(sdc_cmdsta & SDC_CMDSTA_CMDTO)
{
kal_prompt_trace(MOD_MSDC_HISR,"[MSDC]:cmd timeout");
return ERR_CMD_TIMEOUT;
}
else if(sdc_cmdsta & SDC_CMDSTA_RSPCRCERR)
{
kal_prompt_trace(MOD_MSDC_HISR,"[MSDC]:cmd crc");
return ERR_CMD_RSPCRCERR;
}
else if(sdc_cmdsta & SDC_CMDSTA_CMDRDY)
return NO_ERROR;
}
#endif
return NO_ERROR;
}
/*************************************************************************
* FUNCTION
* SD_WaitDatRdyOrTo
*
* DESCRIPTION
* Wait until data ready or timeout
*
* PARAMETERS
*
* RETURNS
* SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
* Interrupt driven and polling are both implemented
*
*************************************************************************/
SDC_CMD_STATUS SD_WaitDatRdyOrTo(void)
{
MSDC_START_TIMER(MSDC_TIMEOUT_PERIOD_DAT);
#ifdef MSDC_USE_INT
{
kal_uint16 sdc_datsta = 0;
kal_uint32 flags = 0;
if(!gMSDC_Handle.mIsPresent)
return ERR_CARD_NOT_PRESENT;
kal_retrieve_eg_events(MSDC_Events,EVENT_SDDATIRQ,KAL_AND_CONSUME,&flags,KAL_SUSPEND);
MSDC_STOP_TIMER();
sdc_datsta = *(volatile kal_uint16*)SDC_DATSTA;
gMSDC_Handle.dat_sta = sdc_datsta;
if(sdc_datsta & SDC_DATSTA_DATTO)
{
kal_prompt_trace(MOD_MSDC_HISR,"[MSDC]:dat timeout");
return ERR_DAT_TIMEOUT;
}
else if(sdc_datsta & SDC_DATSTA_DATCRCERR)
{
kal_prompt_trace(MOD_MSDC_HISR,"[MSDC]:dat crc");
return ERR_DAT_CRCERR;
}
else if(sdc_datsta & SDC_DATSTA_BLKDONE)
return NO_ERROR;
}
#else
{
volatile kal_uint16 sdc_datsta;
while(!(sdc_datsta = *(volatile kal_uint16*)SDC_DATSTA)
&& MSDC_Check_Card_Present() && !gMSDC_Handle.is_timeout);
MSDC_STOP_TIMER();
MSDC_CLR_INT();
gMSDC_Handle.dat_sta = sdc_datsta;
if(sdc_datsta & SDC_DATSTA_DATTO)
{
kal_prompt_trace(MOD_MSDC_HISR,"[MSDC]:dat timeout");
return ERR_DAT_TIMEOUT;
}
else if(sdc_datsta & SDC_DATSTA_DATCRCERR)
{
kal_prompt_trace(MOD_MSDC_HISR,"[MSDC]:dat crc");
return ERR_DAT_CRCERR;
}
else if(sdc_datsta & SDC_DATSTA_BLKDONE)
return NO_ERROR;
}
#endif
return NO_ERROR;
}
/*************************************************************************
* FUNCTION
* SD_WaitCardNotBusy
*
* DESCRIPTION
* Wait until card is not busy (R1b)
*
* PARAMETERS
*
* RETURNS
* void
*
* GLOBALS AFFECTED
*
* NOTE
* Interrupt driven and polling are both implemented
*
*************************************************************************/
SDC_CMD_STATUS SD_WaitCardNotBusy(void)
{
MSDC_START_TIMER(MSDC_TIMEOUT_PERIOD_CMD);
#ifdef MSDC_USE_INT
{
kal_uint32 flags = 0;
if(!gMSDC_Handle.mIsPresent)
return;
kal_retrieve_eg_events(MSDC_Events,EVENT_SDR1BIRQ,KAL_AND_CONSUME,&flags,KAL_SUSPEND);
}
#else
{
while(SD_IS_R1B_BUSY && MSDC_Check_Card_Present() && !gMSDC_Handle.is_timeout);
MSDC_CLR_INT();
MSDC_STOP_TIMER();
}
#endif
return NO_ERROR;
}
/*************************************************************************
* FUNCTION
* SD_CheckStatus
*
* DESCRIPTION
* Check command status
*
* PARAMETERS
*
* RETURNS
* SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
*
*************************************************************************/
SDC_CMD_STATUS SD_CheckStatus()
{
kal_uint32 status;
MSDC_ReadReg32(SDC_RESP0,&status);
if((status & SDC_CSTA_MASK)==0 )
return NO_ERROR;
if(status &SDC_CARD_IS_LOCKED)
return CARD_IS_LOCKED;
return ERR_STATUS;
}
/*************************************************************************
* FUNCTION
* SD_Send_Cmd
*
* DESCRIPTION
* to launch the command packet to the card
*
* PARAMETERS
* 1. cmd: the content of SDC_CMD register
* 2. arg: the argument(if the command need no argument, fill it with 0)
*
* RETURNS
* SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
* 1. Check if controller is available before launch any commands
* 2. Maybe add check if card is busy (R1b)
*************************************************************************/
SDC_CMD_STATUS SD_Send_Cmd(kal_uint32 cmd, kal_uint32 arg)
{
SDC_CMD_STATUS status;
MSDC_START_TIMER(MSDC_TIMEOUT_PERIOD_CMD);
// check the controller is ready (stop transaction will fail)
if(cmd != SDC_CMD_CMD12)
while(SD_IS_SDC_BUSY && MSDC_Check_Card_Present() && !gMSDC_Handle.is_timeout);
else
while(SD_IS_CMD_BUSY && MSDC_Check_Card_Present() && !gMSDC_Handle.is_timeout);
MSDC_STOP_TIMER();
MSDC_CLR_INT();
// fill out the argument
MSDC_WriteReg32(SDC_ARG,arg);
// launch the command
MSDC_WriteReg32(SDC_CMD,cmd);
if((status = SD_WaitCmdRdyOrTo())!=NO_ERROR)
return status;
return NO_ERROR;
}
/*************************************************************************
* FUNCTION
* SD_Reset
*
* DESCRIPTION
* reset all cards to idle state
*
* PARAMETERS
* 1. cmd: the content of SDC_CMD register
* 2. arg: the argument(if the command need no argument, fill it with 0)
*
* RETURNS
* SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
*
*************************************************************************/
SDC_CMD_STATUS SD_Reset(void)
{
SDC_CMD_STATUS status;
status = SD_Send_Cmd(SDC_CMD_CMD0,SDC_NO_ARG);
gSD.mState = IDLE_STA;
return status;
}
/*************************************************************************
* FUNCTION
* SD_Cmd55
*
* DESCRIPTION
* APP_CMD: inidicate to the card that the next command is an application specified command
* rather than a standard command
*
* PARAMETERS
* rca: relative card address
*
* RETURNS
* SDC_CMD_STATUS
*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -