📄 sd.c
字号:
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)
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;
}
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)
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;
}
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)
if(gSD.flags & SD_FLAG_SD_TYPE_CARD )
#else
if(gMSDC_Handle.mMSDC_type == SD_CARD)
#endif
{
//read RCA form card
if((status = SD_Send_Cmd(SDC_CMD_CMD3_SD,SDC_NO_ARG))!=NO_ERROR)
return status;
//read R6
MSDC_ReadReg32(SDC_RESP0, &resp);
*pRca = resp >> 16;
gSD.mRCA =*pRca;
}
else
{
//assign RCA to card
if((status = SD_Send_Cmd(SDC_CMD_CMD3_MMC,(kal_uint32)SDC_RCA_MMC<<16))!=NO_ERROR)
return status;
//read R1
MSDC_ReadReg32(SDC_RESP0, &resp);
SD_GetStatus(SDC_RCA_MMC,&resp);
state = 0;
GetBitFieldN((kal_uint8*)&state,(kal_uint8*)&resp,9,4);
if(STBY_STA != state)
return ERR_RCA_FAIL;
*pRca = gSD.mRCA = SDC_RCA_MMC;
}
gSD.mState = STBY_STA;
return NO_ERROR;
}
/*************************************************************************
* FUNCTION
* SD_SetDSR
*
* DESCRIPTION
* set default value to the DSR
*
* PARAMETERS
*
* RETURNS
* SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
* SDC_DSR_DEFAULT(0x404)
*
*************************************************************************/
SDC_CMD_STATUS SD_SetDSR(void)
{
return SD_Send_Cmd(SDC_CMD_CMD4,(kal_uint32)SDC_DSR_DEFAULT<<16);
}
/*************************************************************************
* FUNCTION
* SD_SelectCard
*
* DESCRIPTION
* select/deselect card
*
* PARAMETERS
* rca: relative card address
*
* RETURNS
* SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
*
*************************************************************************/
SDC_CMD_STATUS SD_SelectCard(kal_uint16 rca)
{
SDC_CMD_STATUS status;
if((status = SD_Send_Cmd(SDC_CMD_CMD7,(kal_uint32)rca<<16))!=NO_ERROR)
return status;
//read R1b
if((status = SD_WaitCardNotBusy())!=NO_ERROR)
return status;
if((status = SD_CheckStatus())!=NO_ERROR)
return status;
return NO_ERROR;
}
/*************************************************************************
* FUNCTION
* SD_GetCSD
*
* DESCRIPTION
* Get CSD from addressed card
*
* PARAMETERS
* rca: relative card address
* Csd: used for containing read CSD
*
* RETURNS
* SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
*
*************************************************************************/
SDC_CMD_STATUS SD_GetCSD(kal_uint16 rca, kal_uint32 Csd[4])
{
SDC_CMD_STATUS status;
kal_uint32 i;
if((status = SD_Send_Cmd(SDC_CMD_CMD9,(kal_uint32)rca<<16))!=NO_ERROR)
return status;
// read R2
for(i=0;i<4;i++)
MSDC_ReadReg32((volatile kal_uint32 *)(SDC_RESP0+i*4), &Csd[i]);
// analysis CSD...
SD_AnalysisCSD(Csd);
return NO_ERROR;
}
// addressed send CID
SDC_CMD_STATUS SD_GetAddressedCID(kal_uint16 rca, kal_uint32 Cid[4])
{
SDC_CMD_STATUS status;
kal_uint32 i;
if((status = SD_Send_Cmd(SDC_CMD_CMD10,(kal_uint32)rca<<16))!=NO_ERROR)
return status;
// read R2
for(i=0;i<4;i++)
MSDC_ReadReg32((volatile kal_uint32 *)(SDC_RESP0+i*4), &Cid[i]);
return NO_ERROR;
}
/*************************************************************************
* FUNCTION
* SD_StopTrans
*
* DESCRIPTION
* Stop Muli-Block operation
*
* PARAMETERS
*
* RETURNS
* SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
* definition of SD_STOP_SLOW is used for some erroneous card
*************************************************************************/
SDC_CMD_STATUS SD_StopTrans(kal_bool isTx)
{
SDC_CMD_STATUS status;
if((status = SD_Send_Cmd(SDC_CMD_CMD12,SDC_NO_ARG))!=NO_ERROR)
return status;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -