📄 sd.c
字号:
}
/*****************************************************************************/
// Description: This function is used to set read timeout times which will be used in read operating.
// Author: Benjamin.Wang
// Note:
/*****************************************************************************/
PUBLIC uint32 SD_GetReadTimeout( // return the timeout value
SD_CARD_T* ptSDCard // the card vector
)
{
if(!SD_RegisterVerify(ptSDCard)) //verify the SDCard vector
{
return 0;
}
return ptSDCard->uiReadTimeout;
}
/*****************************************************************************/
// Description: This function is used to set write timeout times which will be used in read operating.
// Author: Benjamin.Wang
// Note:
/*****************************************************************************/
PUBLIC uint32 SD_SetWriteTimeout( // return SD_SUCCESS
SD_CARD_T* ptSDCard, // the card vector
uint32 uiWriteTimeout // wtite timeout times
)
{
if(!SD_RegisterVerify(ptSDCard)) //verify the SDCard vector
{
return SD_UNREGISTER;
}
ptSDCard->uiWriteTimeout = uiWriteTimeout;
return SD_SUCCESS;
}
/*****************************************************************************/
// Description: This function is used to set write timeout times which will be used in write operating.
// Author: Benjamin.Wang
// Note:
/*****************************************************************************/
PUBLIC uint32 SD_GetWriteTimeout( // return the timeout value
SD_CARD_T* ptSDCard // the card vector
)
{
if(!SD_RegisterVerify(ptSDCard)) //verify the SDCard vector
{
return 0;
}
return ptSDCard->uiWriteTimeout;
}
/*****************************************************************************/
// Description: This function is used to check whether sdcard does exist.
// Author: xingyun.he
// Note:
/*****************************************************************************/
PUBLIC uint32 SD_GetStatus( // return sdcard exist status
SD_CARD_T* ptSDCard // the card vector
)
{
int32 count = 5;
if (PNULL == ptSDCard)
{
SCI_TRACE_LOW("sdcard vector is null");
return SD_NOT_EXIST;
}
if (SD_SUCCESS == SD_Initialize(ptSDCard))
{
return SD_EXIST;
}
else
{
for (; count>0; count--)
{
if (SD_SUCCESS == SD_Initialize(ptSDCard))
{
return SD_EXIST;
}
}
}
return SD_NOT_EXIST;
}
/*****************************************************************************/
// Description: This function is used to get sdcard block length by
// reading READ_BL_LEN in sdcard csd register.
// Author: xingyun.he
// Note: At present, the sdcard driver only supports the card whose capability
// is less than or equal to 2GB.
/*****************************************************************************/
PUBLIC uint32 SD_GetBlockLength( // return the sdcard block length 0 - ERROR!
SD_CARD_T* ptSDCard // the card vector
)
{
uint8 card_specific_data[16 + 2]; //16Bytes CSD + 2 CRC Bytes
if(SD_ReadCSD(ptSDCard, (uint8*)card_specific_data) == SD_SUCCESS)
{
int i;
uint32 read_bl_len;
uint32 block_length = 1;
read_bl_len = card_specific_data[5]&0x0f;
for (i = 0; i < read_bl_len; i++)
{
block_length *= 2;
}
return block_length;
}
return 0;
}
/**---------------------------------------------------------------------------*
** Local Function Definitions *
**---------------------------------------------------------------------------*/
/*****************************************************************************/
// Description: This function is used to write a SD command to Card and get the response.
// Author: Benjamin.Wang
// Note:
/*****************************************************************************/
LOCAL uint32 SD_WriteCmd( // return status. SD_SUCCESS - success
SD_CARD_T* ptSDCard, // the card vector
uint8 ucCmd, // the CMD number
uint8 ucRspType, // the response type
uint8* pucResponse, // response
uint8* pucArgument // argument list
)
{
int i, j;
uint8 response_length;
uint8 tmp;
SD_Delay(ptSDCard->eSPIId, CS_NONE, 1); //After response, SDCard perhaps keep MOSI signal low. So I have to output a data to pull up MOSI signal.
/* All data is sent MSB first*/
/* Send the header/command */
/* Format:
cmd[7:6] : 01
cmd[5:0] : command */
SPI_SetCS(ptSDCard->eSPIId, ptSDCard->uiCSId);
SPI_PutChar(ptSDCard->eSPIId, ptSDCard->uiCSId, (ucCmd & 0x3F) | 0x40);
for(i = 3; i >= 0; i--)
{
SPI_PutChar(ptSDCard->eSPIId, ptSDCard->uiCSId, pucArgument[i]);
}
/* This is the CRC. It only matters what we put here for the first
command. Otherwise, the CRC is ignored for SPI mode unless we
enable CRC checking. */
SPI_PutChar(ptSDCard->eSPIId, ptSDCard->uiCSId, 0x95);
response_length = 0;
switch(ucRspType)
{
case R1:
case R1B:
response_length = 1;
break;
case R2:
response_length = 2;
break;
case R3:
response_length = 5;
break;
default:
break;
}
/* Wait for a response. A response can be recognized by the start bit (a zero) */
i = 0;
j = response_length - 1;
do
{
tmp = (uint8)SPI_GetChar(ptSDCard->eSPIId);
i++;
}
while(((tmp & 0x80) != 0) && i < SD_CMD_TIMEOUT);
/* Just bail if we never got a response */
if(i >= SD_CMD_TIMEOUT)
{
SPI_SetCS(ptSDCard->eSPIId, CS_NONE);
return SD_WRITECMD_TIMEOUT_ERROR;
}
pucResponse[j] = tmp;
j--;
for(; j >= 0; j--)
{
tmp = (uint8)SPI_GetChar(ptSDCard->eSPIId);
pucResponse[j] = tmp;
}
/* If the response is a "busy" type (R1B), then there's some
* special handling that needs to be done. The card will
* output a continuous stream of zeros, so the end of the BUSY
* state is signaled by any nonzero response. The bus idles
* high.
*/
i = 0;
if(ucRspType == R1B)
{
do
{
i++;
tmp = (uint8)SPI_GetChar(ptSDCard->eSPIId);
}
/* This should never time out, unless SPI_DI is grounded.
* Don't bother forcing a timeout condition here. */
while (tmp != 0xFF);
for(i = 0; i < 10; i++)
{
SPI_PutChar(ptSDCard->eSPIId, ptSDCard->uiCSId, 0xFF); //KingMax card's requirement
}
}
for(i = 0; i < 20; i++);
SPI_SetCS(ptSDCard->eSPIId, CS_NONE);
return SD_SUCCESS;
}
/*****************************************************************************/
// Description: This function is used to do a delay. The delay unit is 8 clock.
// Author: Benjamin.Wang
// Note:
/*****************************************************************************/
LOCAL void SD_Delay(
SD_SPIPORT_E eSPIId, // the SPI ID
uint32 uiCSId, // the CS id
uint32 uiNum // delay number
)
{
uint8 i;
/* Null for now */
for (i = 0; i < uiNum; i++)
{
/* Clock out an idle byte (0xFF) */
SPI_PutChar(eSPIId, uiCSId, 0xFF);
}
}
/*****************************************************************************/
// Description: This function is used to pack the argument to the needed order.
// Author: Benjamin.Wang
// Note:
/*****************************************************************************/
LOCAL void SD_Packarg(
uint8* pucArgument, // output argument list
uint32 uiValue // input argument
)
{
pucArgument[3] = (uint8)(uiValue >> 24);
pucArgument[2] = (uint8)(uiValue >> 16);
pucArgument[1] = (uint8)(uiValue >> 8);
pucArgument[0] = (uint8)(uiValue);
}
/*****************************************************************************/
// Description: This function is used to verify the register validity.
// Author: Benjamin.Wang
// Note:
/*****************************************************************************/
LOCAL BOOLEAN SD_RegisterVerify( // return status. SCI_TRUE - Registered
// SCI_FALSE - Unregistered
SD_CARD_T* ptSDCard // the card vector
)
{
SD_CARD_T* ptCurrent;
if(ptSDCard == NULL)
{
return SCI_FALSE; //ptSDCard should not be NULL.
}
ptCurrent = g_sd_ptCardList;
if(ptCurrent != NULL)
{
if(ptCurrent == ptSDCard) //the first element is the card.
{
return SCI_TRUE;
}
while(ptCurrent->pNextElement != NULL) //is tail?
{
ptCurrent = ptCurrent->pNextElement;
if(ptCurrent == ptSDCard) //is the card element?
{
return SCI_TRUE;
}
}
return SCI_FALSE; //Can't find the dest card
}
return SCI_FALSE; //Card list is NULL!
}
/*****************************************************************************/
// Description: After a data block is received the card will respond with a data-response
// token, and if the data block is received with no errors, it will be programmed.
// As long as the card is busy programming, a continuous stream of busy tokens
// will be sent to the host(effectively holding the dataOut line low).
// Author: Benjamin.Wang
// Note:
/*****************************************************************************/
LOCAL uint32 SD_WaitNotBusy (
SD_CARD_T* ptSDCard // the card vector
)
{
uint8 ichar;
int count;
count = 0;
/* Check for the busy flag (set on a write block) */
while(ptSDCard->bBusyFlag == SCI_TRUE)
{
count++;
if (count > SD_TIMEOUT)
{
return SD_WAITNOTBUSY_TIMEOUT;
}
ichar = (uint8)SPI_GetChar(ptSDCard->eSPIId);
if(ichar == 0xFF)
{
ptSDCard->bBusyFlag = SCI_FALSE;
}
}
return SD_SUCCESS;
}
/**---------------------------------------------------------------------------*
** Compiler Flag *
**---------------------------------------------------------------------------*/
#ifdef __cplusplus
}
#endif // End of sd.c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -