📄 sd.c
字号:
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);
if((status = SD_Send_Cmd(SDC_CMD_CMD18,data_adrs))!=NO_ERROR)
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;
if(gSD.mWPEnabled)
return ERR_WRITE_PROTECT;
EnableMSDC_DMA();
count = MSDC_SD_BLOCK_SIZE;
MSDC_DMATransferFirst((kal_uint32)txbuffer,count,KAL_TRUE);
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;
if(gSD.mWPEnabled)
return ERR_WRITE_PROTECT;
EnableMSDC_DMA();
count = MSDC_SD_BLOCK_SIZE;
MSDC_DMATransferFirst((kal_uint32)txbuffer,count,KAL_TRUE);
if((status = SD_Send_Cmd(SDC_CMD_CMD25,address))!=NO_ERROR)
goto ERR_Exit;
// read R1
if((status = SD_CheckStatus())!=NO_ERROR)
goto ERR_Exit;
#if 0
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
#else
{
kal_uint32 j;
for(j=0;j<num;j++)
{
if(gMSDC_Handle.mIsInitialized == KAL_FALSE)
{
status = ERR_CARD_NOT_PRESENT;
goto ERR_Exit;
}
if(j!=0)
MSDC_DMATransferFirst((kal_uint32)txbuffer,count,KAL_TRUE);
status = MSDC_DMATransferFinal();
if(status != NO_ERROR)
goto ERR_Exit;
txbuffer += count;
if((status = SD_WaitDatRdyOrTo())!=NO_ERROR)
goto ERR_Exit;
}
}
#endif
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;
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)
// failed to use DMA with burst mode
MSDC_START_TIMER(MSDC_TIMEOUT_PERIOD_DAT);
for(i=0;i<2;)
{
if(!gMSDC_Handle.mIsPresent)
return ERR_CARD_NOT_PRESENT;
if(gMSDC_Handle.is_timeout)
break;
if(!MSDC_IS_FIFO_EMPTY)
{
*(kal_uint32*)(scr+i) = *(volatile kal_uint32*)MSDC_DAT;
i++;
}
}
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
// restore block length
if((status = SD_SetBlength(blklen))!=NO_ERROR)
return status;
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;
//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);
if((status = SD_Send_Cmd(SDC_CMD_CMD8_MMC40,SDC_NO_ARG))!=NO_ERROR)
return status;
//read R1
if((status = SD_CheckStatus())!=NO_ERROR)
return status;
// read the block of 512 bytes (make sure the rxbuffer is 4 byte aligned)
EnableMSDC_DMA();
status = MSDC_DMATransferFinal();
if(status != NO_ERROR)
goto ERR_Exit;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -