📄 sd.c
字号:
* 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_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)
{
kal_uint8 counter,timeout;
kal_uint32 _ocr;
// Fill out the OCR into SDC_ARG
// VDD voltage window range form 2.8~3.1
counter = 0;
do{
MSDC_START_TIMER(MSDC_TIMEOUT_PERIOD_DAT);
while((MSDC_IS_BUSY)
&& MSDC_Check_Card_Present() && !gMSDC_Handle.is_timeout);
MSDC_STOP_TIMER();
MSDC_WriteReg32(SDC_ARG,SDC_OCR_DEFAULT);
// launch the command 1
MSDC_WriteReg32(SDC_CMD,SDC_CMD_CMD1);
// wait until response arrives
// polling SDC_STA to make sure response is received or timeout
if(SD_WaitCmdRdyOrTo() == ERR_CMD_TIMEOUT)
{
timeout = KAL_TRUE;
continue;
}
timeout = KAL_FALSE;
//read the R3 response which contains card's OCR
MSDC_ReadReg32(SDC_RESP0, &_ocr);
if(!gMSDC_Handle.mIsPresent)
return MSDC_CARD_NOT_PRESENT;
if(!(_ocr&SDC_OCR_BUSY))
kal_sleep_task(10);
// check card power up status bit
}while(!(_ocr&SDC_OCR_BUSY) && (counter++ < TRY_OCR));
if(timeout)
return ERR_CMD_TIMEOUT;
if(counter == TRY_OCR +1)
return ERR_R3_OCR_BUSY;
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_uint8 counter, timeout;
kal_uint32 _ocr = 0, ocr_i;
counter = 0;
ocr_i = SDC_OCR_QUERY;
do{
//dbg_print("OCR %d \r\n",counter);
MSDC_START_TIMER(MSDC_TIMEOUT_PERIOD_DAT);
while((MSDC_IS_BUSY)
&& MSDC_Check_Card_Present() && !gMSDC_Handle.is_timeout);
MSDC_STOP_TIMER();
status=SD_Cmd55(SDC_RCA_DEFAULT);
if(status != NO_ERROR)
{
SD_Reset();
continue;
}
// send CMD41
MSDC_START_TIMER(MSDC_TIMEOUT_PERIOD_DAT);
while((MSDC_IS_BUSY)
&& MSDC_Check_Card_Present() && !gMSDC_Handle.is_timeout);
MSDC_STOP_TIMER();
MSDC_WriteReg32(SDC_ARG,ocr_i);
MSDC_WriteReg32(SDC_CMD,SDC_CMD_CMD41_SD);
// polling SDC_STA to make sure response is received or timeout
if(SD_WaitCmdRdyOrTo() == ERR_CMD_TIMEOUT)
{
timeout = KAL_TRUE;
continue;
}
timeout = KAL_FALSE;
MSDC_ReadReg32(SDC_RESP0, &_ocr);
if((_ocr & SDC_OCR_DEFAULT) == 0)
return ERR_OCR_NOT_SUPPORT;
ocr_i = SDC_OCR_DEFAULT;
if(!gMSDC_Handle.mIsPresent)
return ERR_CARD_NOT_PRESENT;
//delay for card busy
if(!(_ocr&SDC_OCR_BUSY))
{
if(kal_query_systemInit()==KAL_TRUE)
GPTI_BusyWait(10);
else
kal_sleep_task(10);
}
}while(!(_ocr&SDC_OCR_BUSY) && (counter++ < TRY_OCR));
if(timeout)
return ERR_CMD_TIMEOUT;
if(counter == TRY_OCR +1)
return ERR_R3_OCR_BUSY;
gMSDC_Handle.mMSDC_type = SD_CARD;
gSD.mInactive = KAL_FALSE;
gSD.mSDC_ocr = _ocr;
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(gMSDC_Handle.mMSDC_type == SD_CARD)
{
//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 if(gMSDC_Handle.mMSDC_type == MMC_CARD)// MMC card Cmd3
{
//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;
}
else
return ERR_INVALID_CARD;
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;
if(isTx)
SD_WaitCardNotBusy();
#ifdef SD_STOP_SLOW
while(*(volatile kal_uint16*)(SDC_STA) & SDC_STA_R1BSY);
do{
SD_GetStatus(gSD.mRCA,(kal_uint32*)&status);
}while((status & R1_CUR_STATE) >> 9 != TRAN_STA);
#endif
return NO_ERROR;
}
/*************************************************************************
* FUNCTION
* SD_GetStatus
*
* DESCRIPTION
* addressed send status
*
* PARAMETERS
*
* RETURNS
* SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
*
*************************************************************************/
SDC_CMD_STATUS SD_GetStatus(kal_uint16 rca, kal_uint32* resp)
{
SDC_CMD_STATUS status;
if((status = SD_Send_Cmd(SDC_CMD_CMD13,(kal_uint32)rca <<16))!=NO_ERROR)
return status;
MSDC_ReadReg32(SDC_RESP0,resp);
return NO_ERROR;
}
/*************************************************************************
* FUNCTION
* SD_SetBlength
*
* DESCRIPTION
* set block length
*
* PARAMETERS
* BKLength: block length u want to set
*
* RETURNS
* SDC_CMD_STATUS
*
* GLOBALS AFFECTED
* gSD.mBKLength
*
* NOTE
*
*************************************************************************/
SDC_CMD_STATUS SD_SetBlength(kal_uint32 BKLength)
{
SDC_CMD_STATUS status;
// maximal value of block length is 2048
if(BKLength > SDC_MAX_BKLENGTH)
return ERR_INVALID_BKLENGTH;
if(!gSD.mCSD.r_blk_part && BKLength < gSD.mCSD.max_r_blk_len )
return ERR_INVALID_BKLENGTH;
if((status = SD_Send_Cmd(SDC_CMD_CMD16,BKLength))!=NO_ERROR)
return status;
//read R1
status = SD_CheckStatus();
// 2. configure the controller
gSD.mBKLength = BKLength;
BitFieldWrite32((kal_uint32*)SDC_CFG,BKLength,SDC_CFG_BLKLEN);
return NO_ERROR;
}
/*************************************************************************
* FUNCTION
* SD_ReadSingleBlock
*
* DESCRIPTION
* 1. read a single block form data_adrs of card to the rxbuffer
* 2. the block length is set by set block length
*
* PARAMETERS
* data_adrs: starting address to read
* rxbuffer: as name
*
* RETURNS
* SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
* the size of rxbuffer should be 4*n (n : integer)
*
*************************************************************************/
SDC_CMD_STATUS SD_ReadSingleBlock(kal_uint32 data_adrs, kal_uint32* rxbuffer)
{
kal_uint32 count;
SDC_CMD_STATUS status;
EnableMSDC_DMA();
count = MSDC_SD_BLOCK_SIZE;
MSDC_DMATransferFirst((kal_uint32)rxbuffer,count,KAL_FALSE);
if((status = SD_Send_Cmd(SDC_CMD_CMD17,data_adrs))!=NO_ERROR)
goto ERR_Exit;
if((status = SD_CheckStatus())!=NO_ERROR)
goto ERR_Exit;
status = MSDC_DMATransferFinal();
if(status != NO_ERROR)
{
goto ERR_Exit;
}
if((status = SD_WaitDatRdyOrTo())!=NO_ERROR)
goto ERR_Exit;
DisableMSDC_DMA();
MSDC_CLR_FIFO();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -