📄 sd.c
字号:
if(SD_WriteCmd(ptSDCard, CMD38, CMD38_R, g_ucResponse, g_ucArgument) != SD_SUCCESS)
{
return SD_ERASE_CMD38_ERROR;
}
/* Check for an error, like a misaligned write */
if(g_ucResponse[0] != 0)
{
return SD_ERASE_RESPONSE_ERROR3 | (g_ucResponse[0])<<8;
}
/* Signal that the card may be busy, so any subsequent commands
should wait for the busy signalling to end (indicated by a
nonzero response). */
ptSDCard->bBusyFlag = 1;
if ((result = SD_WaitNotBusy( ptSDCard)) != SD_SUCCESS)
{
return result;
}
return SD_SUCCESS;
}
/*****************************************************************************/
// Description: This function is used to set write protect blocks.
// Author: Benjamin.Wang
// Note: This function will be supported in the future.
/*****************************************************************************/
PUBLIC uint32 SD_SetWriteProtect( // return status. SD_SUCCESS - success
SD_CARD_T* ptSDCard, // the card vector
uint32 uiBlocknum // the write protect block num
)
{
//Optional
return SD_SUCCESS;
}
/*****************************************************************************/
// Description: This function is used to clear write protect blocks.
// Author: Benjamin.Wang
// Note: This function will be supported in the future.
/*****************************************************************************/
PUBLIC uint32 SD_ClrWriteProtect( // return status. SD_SUCCESS - success
SD_CARD_T* ptSDCard, // the card vector
uint32 uiBlocknum // the block num
)
{
//Optional
return SD_SUCCESS;
}
/*****************************************************************************/
// Description: This function is used to know whether the block is write protected.
// Author: Benjamin.Wang
// Note: This function will be supported in the future.
/*****************************************************************************/
PUBLIC BOOLEAN SD_GetWriteProtStatus( // return status. SD_SUCCESS - success
SD_CARD_T* ptSDCard, // the card vector
uint32 uiBlocknum // the block num
)
{
//Optional
return SD_SUCCESS;
}
/*****************************************************************************/
// Description: The CID register is 16 bytes long and contains a unique card identification
// number. It is programmed during card manufacturing and cannot be changed
// by miniSD Card hosts. Note that the CID register in the miniSD Card has a
// different structure than the CID register in the MultiediaCard.
// Author: Benjamin.Wang
// Note:
/*****************************************************************************/
PUBLIC uint32 SD_ReadCID( // return status. SD_SUCCESS - success
SD_CARD_T* ptSDCard, // the card vector
uint8* pucData // CID register value. The data length should be 18 bytes: 16 bytes reg value + 2 bytes CRC
)
{
uint32 i = 0;
uint8 tmp;
if(!SD_RegisterVerify(ptSDCard)) //verify the SDCard vector
{
return SD_UNREGISTER;
}
SPI_SetBusClk(ptSDCard->eSPIId, ptSDCard->uiClockRate); // set spi bus clock to max speed
/* Wait until any old transfers are finished */
//SD_WaitNotBusy(ptSDCard);
/* Pack the address */
SD_Packarg(g_ucArgument, 0);
/* Need to add size checking */
if(SD_WriteCmd(ptSDCard, CMD10, CMD10_R, g_ucResponse, g_ucArgument) != SD_SUCCESS)
{
return SD_READCID_CMD10_ERROR;
}
/* Check for an error, like a misaligned read */
if(g_ucResponse[0] != 0)
{
return SD_READCID_RESPONSE_ERROR | (g_ucResponse[0])<<8;
}
/* Re-assert CS to continue the transfer */
SPI_SetCS(ptSDCard->eSPIId, ptSDCard->uiCSId);
/* Wait for the token */
i = 0;
do
{
tmp = (uint8)SPI_GetChar(ptSDCard->eSPIId);
i++;
}
while((tmp == 0xFF) && i < ptSDCard->uiReadTimeout);
if(i == ptSDCard->uiReadTimeout)
{
return SD_READCID_TIMEOUT_ERROR;
}
if((tmp & MSK_TOK_DATAERROR) == 0)
{
/* Clock out a byte before returning */
SPI_PutChar(ptSDCard->eSPIId, ptSDCard->uiCSId, 0xFF);
/* The card returned an error response. Bail and return 0 */
return SD_READCID_TOKEN_ERROR | tmp<<8;
}
for(i = 0; i < 16 + 2; i++) //16Bytes CID + 2 CRC Bytes
{
pucData[i] = (uint8)SPI_GetChar(ptSDCard->eSPIId);
}
SPI_SetCS(ptSDCard->eSPIId, CS_NONE);
SD_Delay(ptSDCard->eSPIId, CS_NONE, 6); //send some clock to let SDCard have enough time to finish it's work.
return SD_SUCCESS;
}
/*****************************************************************************/
// Description: The 32-bit operation conditions register stores the VDD voltage profile of the
// card. The miniSD Card is capable of executing the voltage recognition
// procedure(CMD1) with any standard miniSD Card host using operating
// voltages from 2 to 3.6 Volts.
// Author: Benjamin.Wang
// Note:
/*****************************************************************************/
PUBLIC uint32 SD_ReadOCR( // return status. SD_SUCCESS - success
SD_CARD_T* ptSDCard, // the card vector
uint32* puiData // the OCR shows the voltage range
)
{
if(!SD_RegisterVerify(ptSDCard)) //verify the SDCard vector
{
return SD_UNREGISTER;
}
SPI_SetBusClk(ptSDCard->eSPIId, ptSDCard->uiClockRate); // set spi bus clock to max speed
/* Wait until any old transfers are finished */
//SD_WaitNotBusy(ptSDCard);
/* Pack the address */
SD_Packarg(g_ucArgument, 0);
/* Need to add size checking */
if(SD_WriteCmd(ptSDCard, CMD58, CMD58_R, g_ucResponse, g_ucArgument) != SD_SUCCESS)
{
return SD_READOCR_CMD58_ERROR;
}
/* Check for an error, like a misaligned read */
if(g_ucResponse[4] != 0)
{
return SD_READOCR_RESPONSE_ERROR | (g_ucResponse[4])<<8;
}
*puiData = g_ucResponse[0] + (g_ucResponse[1] << 8) + (g_ucResponse[2] << 16) + (g_ucResponse[3] << 24);
return SD_SUCCESS;
}
/*****************************************************************************/
// Description: The Card Specific Data(CSD) register contains configuration information
// required to access the card data.
// Author: Benjamin.Wang
// Note:
/*****************************************************************************/
PUBLIC uint32 SD_ReadCSD( // return status. SD_SUCCESS - success
SD_CARD_T* ptSDCard, // the card vector
uint8* pucData // CSD register value. The data length should be 18 bytes: 16 bytes reg value + 2 bytes CRC
)
{
uint32 i = 0;
uint8 tmp;
if(!SD_RegisterVerify(ptSDCard)) //verify the SDCard vector
{
return SD_UNREGISTER;
}
SPI_SetBusClk(ptSDCard->eSPIId, ptSDCard->uiClockRate); // set spi bus clock to max speed
/* Wait until any old transfers are finished */
//SD_WaitNotBusy(ptSDCard);
/* Pack the address */
SD_Packarg(g_ucArgument, 0);
/* Need to add size checking */
if(SD_WriteCmd(ptSDCard, CMD9, CMD9_R, g_ucResponse, g_ucArgument) != SD_SUCCESS)
{
return SD_READCSD_CMD9_ERROR;
}
/* Check for an error, like a misaligned read */
if(g_ucResponse[0] != 0)
{
return SD_READCSD_RESPONSE_ERROR | (g_ucResponse[0])<<8;
}
/* Re-assert CS to continue the transfer */
SPI_SetCS(ptSDCard->eSPIId, ptSDCard->uiCSId);
/* Wait for the token */
i = 0;
do
{
tmp = (uint8)SPI_GetChar(ptSDCard->eSPIId);
i++;
}
while((tmp == 0xFF) && i < ptSDCard->uiReadTimeout);
if(i == ptSDCard->uiReadTimeout)
{
return SD_READCSD_TIMEOUT_ERROR;
}
if((tmp & MSK_TOK_DATAERROR) == 0)
{
/* Clock out a byte before returning */
SPI_PutChar(ptSDCard->eSPIId, ptSDCard->uiCSId, 0xFF);
/* The card returned an error response. Bail and return 0 */
return SD_READCSD_TOKEN_ERROR | tmp<<8;
}
for(i = 0; i < 16 + 2; i++) //16Bytes CSD + 2 CRC Bytes
{
pucData[i] = (uint8)SPI_GetChar(ptSDCard->eSPIId);
}
SPI_SetCS(ptSDCard->eSPIId, CS_NONE);
SD_Delay(ptSDCard->eSPIId, CS_NONE, 6); //send some clock to let SDCard have enough time to finish it's work.
return SD_SUCCESS;
}
/*****************************************************************************/
// Description: This function is used to get the card size. Unit: block
// Author: Benjamin.Wang
// Note:
/*****************************************************************************/
PUBLIC uint32 SD_GetDeviceSize( // return the device block number. 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)
{
uint32 blocknr;
uint32 mult = 1;
uint32 c_size;
uint32 c_size_mult;
int32 i;
/*c_size: CSD-Slice [73:62]*/
c_size = ((card_specific_data[6] & 0x3) << 10) | (card_specific_data[7] << 2) | ((card_specific_data[8] & 0xC0) >> 6);
/*c_size_mult: CSD-Slice [49:47]*/
c_size_mult = ((card_specific_data[9] & 0x3) << 1) | ((card_specific_data[10] & 0x80) >> 7);
/*mult = 2 ^ (c_size_mult + 2)*/
for(i = 0; i < c_size_mult + 2; i++)
{
mult *= 2;
}
blocknr = (c_size + 1) * mult;
return blocknr;
}
return 0;
}
/*****************************************************************************/
// Description: This function is used to set the clock rate which will be used in SPI operating.
// Author: Benjamin.Wang
// Note:
/*****************************************************************************/
PUBLIC uint32 SD_SetClockRate( // return SD_SUCCESS
SD_CARD_T* ptSDCard, // the card vector
uint32 uiClockRate // the clock rate
)
{
if(!SD_RegisterVerify(ptSDCard)) //verify the SDCard vector
{
return SD_UNREGISTER;
}
ptSDCard->uiClockRate = uiClockRate;
return SD_SUCCESS;
}
/*****************************************************************************/
// Description: This function is used to set the clock rate which will be used in SPI operating.
// Author: Benjamin.Wang
// Note:
/*****************************************************************************/
PUBLIC uint32 SD_GetClockRate( // return the clock rate.
SD_CARD_T* ptSDCard // the card vector
)
{
if(!SD_RegisterVerify(ptSDCard)) //verify the SDCard vector
{
return 0;
}
return ptSDCard->uiClockRate;
}
/*****************************************************************************/
// Description: This function is used to set read timeout times which will be used in read operating.
// Author: Benjamin.Wang
// Note:
/*****************************************************************************/
PUBLIC uint32 SD_SetReadTimeout( // return SD_SUCCESS
SD_CARD_T* ptSDCard, // the card vector
uint32 uiReadTimeout // read timeout times
)
{
if(!SD_RegisterVerify(ptSDCard)) //verify the SDCard vector
{
return SD_UNREGISTER;
}
ptSDCard->uiReadTimeout = uiReadTimeout;
return SD_SUCCESS;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -