📄 sd.c
字号:
{
kal_mem_cpy(MSDC_Sector, txbuffer, 512);
ptr = txbuffer;
MSDC_DMATransferFirst((kal_uint32)MSDC_Sector,count,KAL_TRUE);
}
}
else
{
MSDC_DMATransferFirst((kal_uint32)txbuffer,count*num,KAL_TRUE);
}
#elif defined(MSDC_MULTI_BLOCK_WRITE)
MSDC_DMATransferFirst((kal_uint32)txbuffer,count*num,KAL_TRUE);
#else
ptr = txbuffer;
MSDC_DMATransferFirst((kal_uint32)ptr,count,KAL_TRUE);
#endif
#ifndef DRV_LSD
if((status = SD_Send_Cmd(SDC_CMD_CMD25,address))!=NO_ERROR)
#else
LSD_HostSetBuffer((kal_uint8 *)txbuffer);
if((status = SD_Send_Cmd(SDC_CMD_CMD25|(num<<20) ,address))!=NO_ERROR)
#endif
goto ERR_Exit;
if((status = SD_CheckStatus())!=NO_ERROR)
goto ERR_Exit;
#if defined(MT6225)
if(dma_issue)
{
if(is_aligned)
{
status = MSDC_DMATransferFinal();
if(status != NO_ERROR)
goto ERR_Exit;
if((status = SD_WaitDatRdyOrTo())!=NO_ERROR)
goto ERR_Exit;
}
else
{
kal_uint32 j;
for(j=0;j<num;j++)
{
if(gMSDC_Handle->mIsPresent == KAL_FALSE)
{
status = ERR_CARD_NOT_PRESENT;
goto ERR_Exit;
}
if(j!=0)
{
kal_mem_cpy(MSDC_Sector, ptr, 512);
MSDC_DMATransferFirst((kal_uint32)MSDC_Sector,count,KAL_TRUE);
}
status = MSDC_DMATransferFinal();
ptr += MSDC_SD_BLOCK_SIZE;
if(status != NO_ERROR)
goto ERR_Exit;
if((status = SD_WaitDatRdyOrTo())!=NO_ERROR)
goto ERR_Exit;
}
}
}
else
{
status = MSDC_DMATransferFinal();
if(status != NO_ERROR)
goto ERR_Exit;
if((status = SD_WaitDatRdyOrTo())!=NO_ERROR)
goto ERR_Exit;
}
#elif defined(MSDC_MULTI_BLOCK_WRITE)
status = MSDC_DMATransferFinal();
if(status != NO_ERROR)
goto ERR_Exit;
if((status = SD_WaitDatRdyOrTo())!=NO_ERROR)
goto ERR_Exit;
#else // not MT6225
{
kal_uint32 j;
for(j=0;j<num;j++)
{
if(gMSDC_Handle->mIsPresent == KAL_FALSE)
{
status = ERR_CARD_NOT_PRESENT;
goto ERR_Exit;
}
if(j!=0)
{
MSDC_DMATransferFirst((kal_uint32)ptr,count,KAL_TRUE);
}
status = MSDC_DMATransferFinal();
ptr += MSDC_SD_BLOCK_SIZE;
if(status != NO_ERROR)
goto ERR_Exit;
if((status = SD_WaitDatRdyOrTo())!=NO_ERROR)
goto ERR_Exit;
}
}
#endif // MT6225
DisableMSDC_DMA();
if((status = SD_StopTrans(KAL_TRUE))!=NO_ERROR)
goto ERR_Exit;
MSDC_CLR_INT();
#ifdef MSDC_USE_INT
kal_set_eg_events(MSDC_Events, 0, KAL_AND);
#endif
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_SetBusWidth
*
* DESCRIPTION
* ACMD6: set the data width 00 for 1 bit, 10 for 4 bits
*
* PARAMETERS
* width: indicate the bus width
*
* RETURNS
* SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
* Not every card support 4-bits bus
* only for SD
*
*************************************************************************/
SDC_CMD_STATUS SD_SetBusWidth(SD_BITWIDTH width)
{
SDC_CMD_STATUS status;
// check if card support 4 bits bus
if((width == BIT_4W) && !(gSD->mSCR.bus_width&0x04))
return ERR_NOT_SUPPORT_4BITS;
// send APP_CMD
if((status = SD_Cmd55(gSD->mRCA))!=NO_ERROR)
return status;
// send cmd6
if((status = SD_Send_Cmd(SDC_CMD_ACMD6,width))!=NO_ERROR)
return status;
//read R1
if((status = SD_CheckStatus())!=NO_ERROR)
return status;
// set the controler MDLEN to enalbe 4bits bus width
MSDC_SET_BIT32(SDC_CFG,SDC_CFG_MDLEN);
gSD->bus_width = 4;
return NO_ERROR;
}
/*************************************************************************
* FUNCTION
* SD_ReadSCR
*
* DESCRIPTION
* ACMD51: read the SD Configuration Register(8bytes block read)
*
* PARAMETERS
* scr: used for store SCR
*
* RETURNS
* SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
* Make sure the size of SCR is 8 bytes
*
*************************************************************************/
SDC_CMD_STATUS SD_ReadSCR(kal_uint32* scr)
{
SDC_CMD_STATUS status;
kal_uint32 blklen,i, t1;
ASSERT((kal_uint32)scr % 4 == 0);
// save the original block length
blklen = gSD->mBKLength;
// set block length(MSDC_CFG)
if((status = SD_SetBlength(8))!=NO_ERROR)
return status;
// send APP_CMD
if((status = SD_Cmd55(gSD->mRCA))!=NO_ERROR)
return status;
// send command
if((status = SD_Send_Cmd(SDC_CMD_ACMD51,SDC_NO_ARG))!=NO_ERROR)
return status;
//read R1
if((status = SD_CheckStatus())!=NO_ERROR)
return status;
// read data(8bytes)
#ifndef DRV_LSD
// failed to use DMA with burst mode
t1 = drv_get_current_time();
MSDC_START_TIMER(MSDC_TIMEOUT_PERIOD_DAT);
for(i=0;i<2;)
{
if(drv_get_duration_ms(t1) > MSDC_TIMEOUT_PERIOD_DAT*11)
gMSDC_Handle->is_timeout = KAL_TRUE;
if(!gMSDC_Handle->mIsPresent)
return ERR_CARD_NOT_PRESENT;
if(gMSDC_Handle->is_timeout)
return MSDC_GPT_TIMEOUT_ERR;
if(!MSDC_IS_FIFO_EMPTY)
{
*(kal_uint32*)(scr+i) = *(volatile kal_uint32*)MSDC_DAT;
i++;
}
}
#else
LSD_readFIFO(scr ,2);
#endif
MSDC_STOP_TIMER();
// analysis scr
SD_AnalysisSCR(scr);
// clean EVENT_SDDATIRQ
#ifdef MSDC_USE_INT
kal_set_eg_events(MSDC_Events, 0, KAL_AND);
#endif
MSDC_CLR_FIFO();
return NO_ERROR;
}
/*************************************************************************
* FUNCTION
* SD_SetPreEraseBlk
*
* DESCRIPTION
* ACMD23: set the number of write blocksto be pre-erased before writing
* used for faster multiple Block Write
*
* PARAMETERS
* num: used for storing number of blocks during multi-block operation
*
* RETURNS
* SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
*
*************************************************************************/
SDC_CMD_STATUS SD_SetPreEraseBlk(kal_uint32 num)
{
SDC_CMD_STATUS status;
//[22:0] number of blocks
num &= 0x003FFF;
// send APP_CMD
if((status = SD_Cmd55(gSD->mRCA))!=NO_ERROR)
return status;
// send CMD23
if((status = SD_Send_Cmd(SDC_CMD_ACMD23,num))!=NO_ERROR)
return status;
//read R1
if((status = SD_CheckStatus())!=NO_ERROR)
return status;
return NO_ERROR;
}
/*************************************************************************
* FUNCTION
* SD_EraseCmdClass
*
* DESCRIPTION
* groups of erase commands including CMD32 ~CMD38
*
* PARAMETERS
* cmd: indicate which command to execute
* address: starting address wiht write protection
*
* RETURNS
* SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
* CMD34~CMD37 are only for MMC
*
*************************************************************************/
SDC_CMD_STATUS SD_EraseCmdClass(kal_uint32 cmd ,kal_uint32 address)
{
SDC_CMD_STATUS status;
if(cmd != SDC_CMD_CMD38)
{
if((status = SD_Send_Cmd(cmd,address))!=NO_ERROR)
return status;
}
else if((status = SD_Send_Cmd(cmd,SDC_NO_ARG))!=NO_ERROR)
return status;
//read R1
if((status = SD_CheckStatus())!=NO_ERROR)
return status;
if(cmd == SDC_CMD_CMD38)
{
SD_WaitCardNotBusy();
do{
SD_GetStatus(gSD->mRCA,(kal_uint32*)&status);
if(gMSDC_Handle->mIsPresent == KAL_FALSE)
break;
}while(CurState(status)!= TRAN_STA);
}
return NO_ERROR;
}
/*************************************************************************
* FUNCTION
* SD_Switch_MMC40
*
* DESCRIPTION
* CMD6: set the command set or write to the EXT_CSD (for MMC4.0)
*
* PARAMETERS
* access: access mode
* index: index to EXT_CSD
* value: value to write to EXT_CSD
* set: selected command set
*
* RETURNS
* SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
*
*************************************************************************/
SDC_CMD_STATUS SD_Switch_MMC40(kal_uint8 access, kal_uint8 index, kal_uint8 value, kal_uint8 set)
{
SDC_CMD_STATUS status;
kal_uint32 arg = 0;
arg = (access<<24)|(index<<16)|(value<<8)|set;
// send command
if((status = SD_Send_Cmd(SDC_CMD_CMD6_MMC40,arg))!=NO_ERROR)
return status;
#ifdef DRV_LSD
//read R1b
if((status = SD_WaitCardNotBusy())!=NO_ERROR)
return status;
#endif
//read R1
if((status = SD_CheckStatus())!=NO_ERROR)
return status;
return NO_ERROR;
}
/*************************************************************************
* FUNCTION
* SD_SendEXTCSD_MMC40
*
* DESCRIPTION
* CMD8: read the content of EXT_CSD register
*
* PARAMETERS
* kal: access mode
* index: index to EXT_CSD
* value: value to write to EXT_CSD
* set: selected command set
*
* RETURNS
* SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
*
*************************************************************************/
SDC_CMD_STATUS SD_SendEXTCSD_MMC40(kal_uint32* rxbuffer)
{
SDC_CMD_STATUS status;
kal_bool retry_4bit = KAL_FALSE;
start:
// read the block of 512 bytes (make sure the rxbuffer is 4 byte aligned)
EnableMSDC_DMA();
MSDC_DMATransferFirst((kal_uint32)rxbuffer,128,KAL_FALSE);
#ifdef DRV_LSD
LSD_HostSetBuffer((kal_uint8 *)rxbuffer);
#endif
if((status = SD_Send_Cmd(SDC_CMD_CMD8_MMC40,SDC_NO_ARG))!=NO_ERROR)
goto ERR_Exit;
//read R1
if((status = SD_CheckStatus())!=NO_ERROR)
goto ERR_Exit;
// read the block of 512 bytes (make sure the rxbuffer is 4 byte aligned)
status = MSDC_DMATransferFinal();
if(status != NO_ERROR)
goto ERR_Exit;
if((status = SD_WaitDatRdyOrTo())!=NO_ERROR)
goto ERR_Exit;
DisableMSDC_DMA();
MSDC_CLR_FIFO();
gSD->mCSD.ext_csd = (T_EXT_CSD_MMC40 *)rxbuffer;
return NO_ERROR;
ERR_Exit:
if(retry_4bit == KAL_FALSE)
{
retry_4bit = KAL_TRUE;
MSDC_SET_BIT32(SDC_CFG,SDC_CFG_MDLEN);
gSD->bus_width = 4;
goto start;
}
MSDC_CLR_BIT32(SDC_CFG,SDC_CFG_MDLEN);
gSD->bus_width = 1;
DisableMSDC_DMA();
MSDC_CLR_FIFO();
RESET_MSDC();
return status;
}
/*************************************************************************
* FUNCTION
* SD_Switch_SD11
*
* DESCRIPTION
* CMD6: switch command to query and select the specific functions. (SD1.1 or later)
* PARAMETERS
* arg: argument
* resp: buffer to contain the ther 64 bytes status information
*
* RETURNS
* SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
*
*************************************************************************/
SDC_CMD_STATUS SD_Switch_SD11(kal_uint32 arg, T_SWITCH_STATUS* info)
{
SDC_CMD_STATUS status = NO_ERROR;
BitFieldWrite32((kal_uint32*)SDC_CFG,SD_CMD6_RESP_LEN,SDC_CFG_BLKLEN);
EnableMSDC_DMA();
MSDC_DMATransferFirst((kal_uint32)info,(SD_CMD6_RESP_LEN>>2),KAL_FALSE);
if((status = SD_Send_Cmd(SDC_CMD_CMD6_SD11,arg))!=NO_ERROR)
goto exit;
if((status = SD_CheckStatus())!=NO_ERROR)
goto exit;
status = MSDC_DMATransferFinal();
exit:
DisableMSDC_DMA();
return status;
}
/*************************************************************************
* FUNCTION
* SD_Switch_SD11
*
* DESCRIPTION
* Enable the high speed interface to support up to 50M Hz clock
*
* PARAMETERS
* arg: argument
* resp: buffer to contain the ther 64 bytes status information
*
* RETURNS
* SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
*
*************************************************************************/
SDC_CMD_STATUS SD_SelectHighSpeed_SD11(void)
{
SDC_CMD_STATUS status;
T_SWITCH_STATUS *p = (T_SWITCH_STATUS*)MSDC_Sector;
if((status = SD_Switch_SD11(SD_CMD6_QUERY_HIGH_SPEED, p))!=NO_ERROR)
return status;
if(p->max_current == 0)
return ERR_SD_HS_FAIL;
if((p->group1_info & (1 << SD_FUNC_HIGH_SPEED)) &&
(p->group1_result == SD_FUNC_HIGH_SPEED))
{
if((status = SD_Switch_SD11(SD_CMD6_SELECT_HIGH_SPEED, p))!=NO_ERROR)
return status;
if(p->max_current == 0)
return ERR_SD_HS_FAIL;
if(p->group1_result == SD_FUNC_HIGH_SPEED)
gSD->flags |= SD_FLAG_HS_SUPPORT;
}
else
return ERR_SD_HS_FAIL;
return NO_ERROR;
}
SDC_CMD_STATUS SD_GoInactive(kal_uint16 rca)
{
SDC_CMD_STATUS status;
if((status = SD_Send_Cmd(SDC_CMD_CMD15,(kal_uint32)rca <<16))!= NO_ERROR)
return status;
return NO_ERROR;
}
SDC_CMD_STATUS SD_ReadStream_MMC(kal_uint32 address, kal_uint32* rxbuffer, kal_uint32 bytes)
{
SDC_CMD_STATUS status;
kal_uint32 i,count;
MSDC_CLR_FIFO();
count = (bytes%4)?(bytes/4+1):(bytes/4);
#ifdef MSDC_DMA
EnableMSDC_DMA();
MSDC_DMATransferFirst((kal_uint32)rxbuffer,count,KAL_FALSE);
#endif
//launch stream read command
if((status = SD_Send_Cmd(SDC_CMD_CMD11_MMC,address)) != NO_ERROR)
{
goto ERR_Exit;
}
//read R1
if((status = SD_CheckStatus())!= NO_ERROR)
{
SD_WaitDatRdyOrTo();
goto ERR_Exit;
}
#ifdef MSDC_DMA
status = MSDC_DMATransferFinal();
if(status != NO_ERROR)
{
goto ERR_Exit;
}
#else
//size assumed to be multiple of 4
for(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -