📄 sd.c
字号:
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++)
{
#ifndef DRV_LSD
MSDC_ReadReg32((volatile kal_uint32 *)(SDC_RESP0+i*4), &Csd[i]);
#else
MSDC_ReadReg32(SDC_RESP0+i, &Csd[i]);
#endif
}
// 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++)
{
#ifndef DRV_LSD
MSDC_ReadReg32((volatile kal_uint32 *)(SDC_RESP0+i*4), &Cid[i]);
#else
MSDC_ReadReg32(SDC_RESP0+i, &Cid[i]);
#endif
}
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;
kal_uint32 retry = 0;
while(retry < 30)
{
if((status = SD_Send_Cmd(SDC_CMD_CMD12,SDC_NO_ARG))!=NO_ERROR)
{
retry ++;
}
else
{
break;
}
}
if(retry >= 30)
{
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);
#ifdef DRV_LSD
LSD_HostSetBuffer((kal_uint8 *)rxbuffer);
#endif
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();
return NO_ERROR;
ERR_Exit:
{
kal_uint32 tmp;
#ifdef MSDC_USE_INT
kal_set_eg_events(MSDC_Events, 0, KAL_AND);
#endif
DisableMSDC_DMA();
RESET_MSDC();
// SD_StopTrans(KAL_FALSE);
SD_GetStatus(gSD->mRCA,(kal_uint32*)&tmp);
MSDC_ReadReg32(SDC_DATSTA,&tmp);
MSDC_CLR_FIFO();
return status;
}
}
/*************************************************************************
* FUNCTION
* SD_ReadMultiBlock
*
* DESCRIPTION
* read num of blocks into rxbuffer
*
* PARAMETERS
* data_adrs: starting address to read
* rxbuffer: as name
* num: number of blocks to read
*
* RETURNS
* SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
*
*************************************************************************/
SDC_CMD_STATUS SD_ReadMultiBlock(kal_uint32 data_adrs, kal_uint32* rxbuffer, kal_uint32 num)
{
SDC_CMD_STATUS status;
kal_uint32 j, count;
#ifndef MSDC_DMA
kal_uint32 i;
#endif
EnableMSDC_DMA();
count = MSDC_SD_BLOCK_SIZE;
MSDC_DMATransferFirst((kal_uint32)rxbuffer,count*num,KAL_FALSE);
#ifndef DRV_LSD
if((status = SD_Send_Cmd(SDC_CMD_CMD18,data_adrs))!=NO_ERROR)
#else
LSD_HostSetBuffer((kal_uint8 *)rxbuffer);
if((status = SD_Send_Cmd(SDC_CMD_CMD18|(num<<20) ,data_adrs))!=NO_ERROR)
#endif
goto ERR_Exit;
if((status = SD_CheckStatus())!=NO_ERROR)
goto ERR_Exit;
count = MSDC_SD_BLOCK_SIZE;
status = MSDC_DMATransferFinal();
if(status != NO_ERROR)
goto ERR_Exit;
if((status = SD_WaitDatRdyOrTo())!=NO_ERROR)
goto ERR_Exit;
MSDC_CLR_INT();
DisableMSDC_DMA();
if(gSD->flags & SD_FLAG_MMC_MRSW_FAIL)
{
kal_uint32 delay = 200;
while(delay--);
}
if((status = SD_StopTrans(KAL_FALSE))!=NO_ERROR)
{
//if((data_adrs/gSD->mBKLength + j) < gSD->mBKNum)
goto ERR_Exit;
}
MSDC_CLR_FIFO();
return NO_ERROR;
ERR_Exit:
#ifdef MSDC_USE_INT
kal_set_eg_events(MSDC_Events, 0, KAL_AND);
#endif
DisableMSDC_DMA();
RESET_MSDC();
SD_StopTrans(KAL_FALSE);
SD_GetStatus(gSD->mRCA,(kal_uint32*)&j);
MSDC_ReadReg32(SDC_DATSTA,&j);
MSDC_CLR_FIFO();
return status;
}
/*************************************************************************
* FUNCTION
* SD_WriteSingleBlock
*
* DESCRIPTION
* write a single block
*
* PARAMETERS
* address: starting address to write
* txbuffer: as name
*
* RETURNS
* SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
* block length is set by Set_Block_Length
*
*************************************************************************/
SDC_CMD_STATUS SD_WriteSingleBlock(kal_uint32 address, kal_uint32* txbuffer)
{
SDC_CMD_STATUS status;
kal_uint32 count;
kal_uint32 *ptr;
#if defined(MT6225)
kal_bool is_aligned;
ECO_VERSION eco;
eco = INT_ecoVersion();
#endif
if(gSD->mWPEnabled)
return ERR_WRITE_PROTECT;
EnableMSDC_DMA();
count = MSDC_SD_BLOCK_SIZE;
#if defined(MT6225)
if(eco <= ECO_E3)
{
is_aligned = ((kal_uint32)txbuffer%4 == 0);
if(is_aligned)
{
ptr = txbuffer;
}
else
{
kal_mem_cpy(MSDC_Sector, txbuffer, 512);
ptr = MSDC_Sector;
}
}
else
{
ptr = txbuffer;
}
#else
ptr = txbuffer;
#endif
EnableMSDC_DMA();
count = MSDC_SD_BLOCK_SIZE;
MSDC_DMATransferFirst((kal_uint32)ptr,count,KAL_TRUE);
#ifdef DRV_LSD
LSD_HostSetBuffer((kal_uint8 *)txbuffer);
#endif
if((status = SD_Send_Cmd(SDC_CMD_CMD24,address))!=NO_ERROR)
goto ERR_Exit;
if((status = SD_CheckStatus())!=NO_ERROR)
goto ERR_Exit;
status = MSDC_DMATransferFinal();
if(status != NO_ERROR)
goto ERR_Exit;
// wait R1b interrupt because cmd24 is configured as R1b response but cmd25 needn't
if((status = SD_WaitCardNotBusy())!=NO_ERROR)
goto ERR_Exit;
DisableMSDC_DMA();
if((status = SD_WaitDatRdyOrTo())!=NO_ERROR)
goto ERR_Exit;
return NO_ERROR;
ERR_Exit:
{
kal_uint32 tmp;
#ifdef MSDC_USE_INT
kal_set_eg_events(MSDC_Events, 0, KAL_AND);
#endif
DisableMSDC_DMA();
RESET_MSDC();
//SD_StopTrans(KAL_TRUE);
SD_GetStatus(gSD->mRCA,(kal_uint32*)&tmp);
MSDC_ReadReg32(SDC_DATSTA,&tmp);
return status;
}
}
/*************************************************************************
* FUNCTION
* SD_WriteMultiBlock
*
* DESCRIPTION
* write num blocks starting at address
*
* PARAMETERS
* address: starting address to write
* txbuffer: as name
* num: number of blocks to write
*
* RETURNS
* SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
* block length is set by Set_Block_Length
*
*************************************************************************/
SDC_CMD_STATUS SD_WriteMultiBlock(kal_uint32 address, kal_uint32* txbuffer, kal_uint32 num)
{
SDC_CMD_STATUS status;
kal_uint32 count;
kal_uint32 *ptr;
#if defined(MT6225)
kal_bool is_aligned, dma_issue;
ECO_VERSION eco;
eco = INT_ecoVersion();
if(eco <= ECO_E3)
dma_issue = KAL_TRUE;
#endif
if(gSD->mWPEnabled)
return ERR_WRITE_PROTECT;
EnableMSDC_DMA();
count = MSDC_SD_BLOCK_SIZE;
#if defined(MT6225)
if(dma_issue)
{
is_aligned = ((kal_uint32)txbuffer%4 == 0);
if(is_aligned)
{
MSDC_DMATransferFirst((kal_uint32)txbuffer,count*num,KAL_TRUE);
}
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -