📄 sd.c
字号:
return ERR_DAT_CRCERR;
}
else if(sdc_datsta & SDC_DATSTA_BLKDONE)
return NO_ERROR;
}
#else
{
volatile kal_uint16 sdc_datsta;
kal_uint32 t1;
t1 = drv_get_current_time();
#ifndef DRV_LSD
while(!(sdc_datsta = *(volatile kal_uint16*)SDC_DATSTA)
#else
while(!(sdc_datsta = LSD_Reg32(SDC_DATSTA))
#endif
&& MSDC_Check_Card_Present() && !gMSDC_Handle->is_timeout)
{
if(drv_get_duration_ms(t1) > MSDC_TIMEOUT_PERIOD_DAT*11)
gMSDC_Handle->is_timeout = KAL_TRUE;
};
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;
}
if(gMSDC_Handle->is_timeout)
return MSDC_GPT_TIMEOUT_ERR;
#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)
{
kal_uint32 t1;
t1 = drv_get_current_time();
MSDC_START_TIMER(MSDC_TIMEOUT_PERIOD_DAT);
#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)
{
if(drv_get_duration_ms(t1) > MSDC_TIMEOUT_PERIOD_DAT*11)
gMSDC_Handle->is_timeout = KAL_TRUE;
};
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;
kal_uint32 t1;
t1 = drv_get_current_time();
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)
{
if(drv_get_duration_ms(t1) > MSDC_TIMEOUT_PERIOD_DAT*11)
gMSDC_Handle->is_timeout = KAL_TRUE;
}
}
else
{
while(SD_IS_CMD_BUSY && MSDC_Check_Card_Present() && !gMSDC_Handle->is_timeout)
{
if(drv_get_duration_ms(t1) > MSDC_TIMEOUT_PERIOD_DAT*11)
gMSDC_Handle->is_timeout = KAL_TRUE;
}
}
MSDC_STOP_TIMER();
if(gMSDC_Handle->is_timeout)
return MSDC_GPT_TIMEOUT_ERR;
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
*
* GLOBALS AFFECTED
*
* NOTE
*
*************************************************************************/
SDC_CMD_STATUS SD_Cmd55(kal_uint16 rca)
{
SDC_CMD_STATUS status;
if((status = SD_Send_Cmd(SDC_CMD_CMD55,(kal_uint32)rca<<16))!=NO_ERROR)
return status;
//read R1
if((status = SD_CheckStatus())!=NO_ERROR)
return status;
//check APP_CMD bit in status register
MSDC_ReadReg32(SDC_RESP0,&status);
if(!(status & R1_APP_CMD_5))
return ERR_APPCMD_FAILED;
return NO_ERROR;
}
/*************************************************************************
* FUNCTION
* SD_Cmd8
*
* DESCRIPTION
* 1. Sends SD Memory Card interface conditions for support larger than 2G cards
* 2. check if the card is compliant to SD2.0 or higher
* 3. only performed while at IDLE state.
*
* PARAMETERS
*
* RETURNS
*
* GLOBALS AFFECTED
* gSD->mIsCMD8
*
*************************************************************************/
void SD_Cmd8(void)
{
kal_uint32 resp;
if(SD_Send_Cmd(SDC_CMD_CMD8,SDC_CMD8_ARG)!=NO_ERROR)
{
dbg_print("SD_Cmd8 fail \r\n");
SD_Reset();
gSD->mCMD8Resp = SD_CMD8_RESP_NORESP;
return;
}
MSDC_ReadReg32(SDC_RESP0,&resp);
if(resp == SDC_CMD8_ARG)
gSD->mCMD8Resp = SD_CMD8_RESP_VALID;
else
gSD->mCMD8Resp = SD_CMD8_RESP_INVALID;
}
/*************************************************************************
* FUNCTION
* SD_Cmd1_MMC
*
* DESCRIPTION
* asks all cards in idle state to send their OCR in the response on the CMD line
*
* PARAMETERS
*
* RETURNS
* SDC_CMD_STATUS
*
* GLOBALS AFFECTED
* gSD
*
* NOTE
* only works for MMC
*
*************************************************************************/
SDC_CMD_STATUS SD_Cmd1_MMC(void)
{
SDC_CMD_STATUS status;
kal_uint32 _ocr, ocr_i, t1, t2;
#if defined(SD_MMC_HIGH_DENSITY_SUPPORT)
if(gSD->mCMD8Resp == SD_CMD8_RESP_INVALID)
return ERR_CMD8_INVALID;
ocr_i = (SDC_OCR_DEFAULT|MMC_HIGH_DESITY_CHECK_BIT);
#else
ocr_i = SDC_OCR_DEFAULT;
#endif
if(gMSDC_Handle->is_init_timeout == KAL_TRUE)
return ERR_R3_OCR_BUSY;
t2 = drv_get_current_time();
do{
t1 = drv_get_current_time();
MSDC_START_TIMER(MSDC_TIMEOUT_PERIOD_DAT);
while((MSDC_IS_BUSY)
&& MSDC_Check_Card_Present() && !gMSDC_Handle->is_timeout)
{
if(drv_get_duration_ms(t1) > MSDC_TIMEOUT_PERIOD_DAT*11)
gMSDC_Handle->is_timeout = KAL_TRUE;
};
MSDC_STOP_TIMER();
if(gMSDC_Handle->is_timeout)
return MSDC_GPT_TIMEOUT_ERR;
MSDC_WriteReg32(SDC_ARG,ocr_i);
MSDC_WriteReg32(SDC_CMD,SDC_CMD_CMD1);
if((status = SD_WaitCmdRdyOrTo()) != NO_ERROR)
{
return status;
}
MSDC_ReadReg32(SDC_RESP0, &_ocr);
if((_ocr & SDC_OCR_DEFAULT) == 0)
return ERR_OCR_NOT_SUPPORT;
if(!gMSDC_Handle->mIsPresent)
return MSDC_CARD_NOT_PRESENT;
if(!(_ocr&SDC_OCR_BUSY))
{
if(drv_get_duration_ms(t2) > MSDC_TIMEOUT_PERIOD_INI)
{
gMSDC_Handle->is_init_timeout = KAL_TRUE;
break;
}
if((kal_query_systemInit() == KAL_TRUE)
#ifdef __TST_WRITE_TO_FILE_ONLY__ /*error recording: considering error recording additionally*/
|| (KAL_TRUE == INT_QueryExceptionStatus())
#endif
)
GPTI_BusyWait(30);
else
kal_sleep_task(7);
}
else
break;
}while(1);
if(gMSDC_Handle->is_init_timeout)
return ERR_CMD_TIMEOUT;
#if defined(SD_MMC_HIGH_DENSITY_SUPPORT)
if((_ocr & MMC_HIGH_DESITY_CHECK_MSK) == MMC_HIGH_DESITY_CHECK_BIT)
{
gSD->flags |= SD_FLAG_HCS_SUPPORT;
gMSDC_Handle->mMSDC_type = MMC42_CARD;
kal_print("MMC4.2 or higher");
}
else
#endif
gMSDC_Handle->mMSDC_type = MMC_CARD;
gSD->mInactive = KAL_FALSE;
gSD->mSDC_ocr = _ocr;
gSD->mState = READY_STA;
return NO_ERROR;
}
/*************************************************************************
* FUNCTION
* SD_Acmd41_SD
*
* DESCRIPTION
* asks all cards in idle state to send their OCR in the response on the CMD line
* OCR: Operation Condition Register
*
* PARAMETERS
*
* RETURNS
* SDC_CMD_STATUS
*
* GLOBALS AFFECTED
* gSD
*
* NOTE
* only works for SD
*
*************************************************************************/
SDC_CMD_STATUS SD_Acmd41_SD(void)
{
SDC_CMD_STATUS status;
kal_uint32 _ocr = 0, ocr_i, t1, t2;
#if defined(SD_MMC_HIGH_DENSITY_SUPPORT)
if(gSD->mCMD8Resp == SD_CMD8_RESP_NORESP)
ocr_i = SDC_OCR_DEFAULT;
else if(gSD->mCMD8Resp == SD_CMD8_RESP_VALID)
ocr_i = (SDC_OCR_DEFAULT|SD_ACMD41_HCS);
else if(gSD->mCMD8Resp == SD_CMD8_RESP_INVALID)
return ERR_CMD8_INVALID;
#else
ocr_i = SDC_OCR_DEFAULT;
#endif
gMSDC_Handle->is_init_timeout = KAL_FALSE;
t2 = drv_get_current_time();
do{
t1 = drv_get_current_time();
MSDC_START_TIMER(MSDC_TIMEOUT_PERIOD_CMD);
while((MSDC_IS_BUSY)
&& MSDC_Check_Card_Present() && !gMSDC_Handle->is_timeout)
{
if(drv_get_duration_ms(t1) > MSDC_TIMEOUT_PERIOD_CMD*11)
gMSDC_Handle->is_timeout = KAL_TRUE;
};
MSDC_STOP_TIMER();
if(gMSDC_Handle->is_timeout)
return MSDC_GPT_TIMEOUT_ERR;
status=SD_Cmd55(SDC_RCA_DEFAULT);
if(status != NO_ERROR)
{
return status;
}
MSDC_START_TIMER(MSDC_TIMEOUT_PERIOD_CMD);
t1 = drv_get_current_time();
while((MSDC_IS_BUSY)
&& MSDC_Check_Card_Present() && !gMSDC_Handle->is_timeout)
{
if(drv_get_duration_ms(t1) > MSDC_TIMEOUT_PERIOD_CMD*11)
gMSDC_Handle->is_timeout = KAL_TRUE;
};
MSDC_STOP_TIMER();
if(gMSDC_Handle->is_timeout)
return MSDC_GPT_TIMEOUT_ERR;
MSDC_WriteReg32(SDC_ARG,ocr_i);
MSDC_WriteReg32(SDC_CMD,SDC_CMD_CMD41_SD);
if((status = SD_WaitCmdRdyOrTo()) != NO_ERROR)
{
return status;
}
MSDC_ReadReg32(SDC_RESP0, &_ocr);
if((_ocr & SDC_OCR_DEFAULT) == 0)
return ERR_OCR_NOT_SUPPORT;
if(!gMSDC_Handle->mIsPresent)
return ERR_CARD_NOT_PRESENT;
if(!(_ocr&SDC_OCR_BUSY))
{
if(drv_get_duration_ms(t2) > MSDC_TIMEOUT_PERIOD_INI)
{
gMSDC_Handle->is_init_timeout = KAL_TRUE;
break;
}
if((kal_query_systemInit() == KAL_TRUE)
#ifdef __TST_WRITE_TO_FILE_ONLY__ /*error recording: considering error recording additionally*/
|| (KAL_TRUE == INT_QueryExceptionStatus())
#endif
)
GPTI_BusyWait(30);
else
kal_sleep_task(7);
}
else
break;
}
while(1);
if(gMSDC_Handle->is_init_timeout)
return ERR_R3_OCR_BUSY;
gSD->mInactive = KAL_FALSE;
gSD->mSDC_ocr = _ocr;
#if defined(SD_MMC_HIGH_DENSITY_SUPPORT)
gSD->flags |= SD_FLAG_SD_TYPE_CARD;
if(_ocr & SD_ACMD41_HCS)
{
gSD->flags |= SD_FLAG_HCS_SUPPORT;
gMSDC_Handle->mMSDC_type = SD20_HCS_CARD;
kal_print("SD2.0 or higher");
}
else if(gSD->mCMD8Resp == SD_CMD8_RESP_VALID)
gMSDC_Handle->mMSDC_type = SD20_LCS_CARD;
else
#endif
gMSDC_Handle->mMSDC_type = SD_CARD;
gSD->mState = READY_STA;
return NO_ERROR;
}
/*************************************************************************
* FUNCTION
* SD_GetCID
*
* DESCRIPTION
* Read Card Identification.
*
* PARAMETERS
*
* RETURNS
* SDC_CMD_STATUS
*
* GLOBALS AFFECTED
* gSD
*
* NOTE
*
*
*************************************************************************/
// Get CID(CMD2)
SDC_CMD_STATUS SD_GetCID(kal_uint32 Cid[4])
{
int i;
SDC_CMD_STATUS status;
if((status = SD_Send_Cmd(SDC_CMD_CMD2,SDC_NO_ARG))!=NO_ERROR)
return status;
//read R2
for(i=0;i<4;i++)
MSDC_ReadReg32((SDC_RESP0+i*sizeof(kal_uint32)), &Cid[i]);
SD_AnalysisCID(Cid);
gSD->mState = IDENT_STA;
return NO_ERROR;
}
/*************************************************************************
* FUNCTION
* SD_ValidateRCA
*
* DESCRIPTION
* assing or read RCA
*
* PARAMETERS
* pRca: used for input or output RCA
*
* RETURNS
* SDC_CMD_STATUS
*
* GLOBALS AFFECTED
* gSD
*
* NOTE
* RCA is assinged to MMC card fixed to SDC_RCA_MMC(1)
*
*************************************************************************/
// assign or read RCA
SDC_CMD_STATUS SD_ValidateRCA(kal_uint16* pRca)
{
SDC_CMD_STATUS status;
kal_uint32 resp;
kal_uint8 state;
#if defined(SD_MMC_HIGH_DENSITY_SUPPORT)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -