📄 sd.c
字号:
return SD_UNREGISTER;
}
else
{
//SCI_PASSERT(0, ("SD Card manage list is NULL!"));
return SD_CARDLIST_NULL;
}
}
/*****************************************************************************/
// Description: This function is used to read one block data.
// Author: Benjamin.Wang
// Note:
/*****************************************************************************/
PUBLIC uint32 SD_ReadBlock( //Return SD_SUCCESS - read success
//SD_UNREGISTER - theSDCard vector has not been registered.
//Return SD_BLOCK_LENGTH_INVALID - the block size is not valid block size or setting failure
//Return SD_FAILURE - read failure
SD_CARD_T* ptSDCard, //SDCard vector
uint32 uiBlocknum, //the dest block num
uint8* pucData, //data buffer pointer
uint32 uiBlockSize //one block size - 1 ~ 512 Bytes
)
{
uint32 i = 0;
uint8 tmp;
uint32 block_address;
if(!SD_RegisterVerify(ptSDCard)) //verify the SDCard vector
{
return SD_UNREGISTER;
}
SPI_SetBusClk(ptSDCard->eSPIId, ptSDCard->uiClockRate); // set spi bus clock to max speed
if(g_sd_default_blocksize != uiBlockSize)
{
//Blocksize is not the same as last operation. We should reconfig it.
if(SD_SetBlockLength(ptSDCard, uiBlockSize) != SD_SUCCESS)
{
return SD_BLOCK_LENGTH_INVALID;
}
}
/* Adjust the block address to a linear address */
//block_address = uiBlocknum << SD_BLOCKSIZE_NBITS;
block_address = uiBlocknum * uiBlockSize;
/* Wait until any old transfers are finished */
//SD_WaitNotBusy(ptSDCard);
/* Pack the address */
SD_Packarg(g_ucArgument, block_address);
/* Need to add size checking */
if(SD_WriteCmd(ptSDCard, CMD17, CMD17_R, g_ucResponse, g_ucArgument) != SD_SUCCESS)
{
return SD_READ_CMD17_ERROR;
}
/* Check for an error, like a misaligned read */
if(g_ucResponse[0] != 0)
{
return SD_READ_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(tmp != SD_TOK_READ_STARTBLOCK)
{
/* 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_READ_TOKEN_ERROR | tmp<<8;
}
if (SD_BLOCKSIZE == uiBlockSize) //When the size of block is 512, DMA read is used
{
for(i = 0; i < uiBlockSize / SD_DMA_READ_LEN; i++)
{
SPI_DmaRead(ptSDCard->eSPIId, pucData + SD_DMA_READ_LEN * i, SD_DMA_READ_LEN);
}
}
else
{
for(i = 0; i < uiBlockSize; i++)
{
pucData[i] = SPI_GetChar(ptSDCard->eSPIId);
}
}
SPI_GetChar(ptSDCard->eSPIId); // 2 CRC bytes
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 read multiple block data.
// Author: Benjamin.Wang
// Note:
/*****************************************************************************/
PUBLIC uint32 SD_ReadMultiBlock( // return status. SD_SUCCESS - success
SD_CARD_T* ptSDCard, // Card vector
uint32 uiStartBlocknum, // the start block number
uint32 uiBlockCounts, // the block count
uint8* pucData, // the data pointer
uint32 uiBlockSize // one block size. For example, 512 bytes
)
{
uint32 i = 0;
int32 j;
uint8 tmp;
uint32 block_address;
if(!SD_RegisterVerify(ptSDCard)) //verify the SDCard vector
{
return SD_UNREGISTER;
}
SPI_SetBusClk(ptSDCard->eSPIId, ptSDCard->uiClockRate); // set spi bus clock to max speed
if(g_sd_default_blocksize != uiBlockSize)
{
//Blocksize is not the same as last operation. We should reconfig it.
if(SD_SetBlockLength(ptSDCard, uiBlockSize) != SD_SUCCESS)
{
return SD_BLOCK_LENGTH_INVALID;
}
}
/* Adjust the block address to a linear address */
block_address = uiStartBlocknum * uiBlockSize;
/* Pack the address */
SD_Packarg(g_ucArgument, block_address);
/* Need to add size checking */
if(SD_WriteCmd(ptSDCard, CMD18, CMD18_R, g_ucResponse, g_ucArgument) != SD_SUCCESS)
{
return SD_READMULTI_CMD18_ERROR;
}
/* Check for an error, like a misaligned read */
if(g_ucResponse[0] != 0)
{
return SD_READMULTI_RESPONSE_ERROR | (g_ucResponse[0])<<8;
}
/* Re-assert CS to continue the transfer */
SPI_SetCS(ptSDCard->eSPIId, ptSDCard->uiCSId);
for(j = 0; j < uiBlockCounts; j++)
{
/* Wait for the token */
i = 0;
do
{
tmp = (uint8)SPI_GetChar(ptSDCard->eSPIId);
i++;
}
while((tmp == 0xFF) && i < ptSDCard->uiReadTimeout);
if(tmp != SD_TOK_READ_STARTBLOCK_M)
{
/* 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_READMULTI_TOKEN_ERROR | tmp<<8;
}
if (SD_BLOCKSIZE == uiBlockSize)
{
for(i = 0; i < uiBlockSize / SD_DMA_READ_LEN; i++)
{
SPI_DmaRead(ptSDCard->eSPIId, pucData + j * uiBlockSize + SD_DMA_READ_LEN * i, SD_DMA_READ_LEN);
}
}
else
{
for (i = 0; i < uiBlockSize; i++)
{
pucData[i + j * uiBlockSize] = SPI_GetChar(ptSDCard->eSPIId);
}
}
SPI_GetChar(ptSDCard->eSPIId); // 2 CRC bytes
SPI_GetChar(ptSDCard->eSPIId);
}
if(SD_WriteCmd(ptSDCard, CMD12, CMD12_R, g_ucResponse, g_ucArgument) != SD_SUCCESS)
{
return SD_READMULTI_CMD12_ERROR;
}
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 write one block data.
// Author: Benjamin.Wang
// Note: The block size is fixed 512 Bytes.
/*****************************************************************************/
PUBLIC uint32 SD_WriteBlock( //SD_SUCCESS - write success
//SD_UNREGISTER - theSDCard vector has not been registered.
//SD_FAILURE - write failure
SD_CARD_T* ptSDCard, //SDCard vector
uint32 uiBlocknum, //the dest block num
const uint8* pucData //data buffer pointer
)
{
uint32 i;
uint32 block_address;
uint8 data_response;
uint32 result, result1;
if(!SD_RegisterVerify(ptSDCard)) //verify the SDCard vector
{
return SD_UNREGISTER;
}
if (g_sd_default_blocksize != SD_BLOCKSIZE)
{
if(SD_SetBlockLength(ptSDCard, SD_BLOCKSIZE) != SD_SUCCESS)
{
return SD_BLOCK_LENGTH_INVALID;
}
}
SPI_SetBusClk(ptSDCard->eSPIId, ptSDCard->uiClockRate); // set spi bus clock to max speed
/* Adjust the block address to a linear address */
block_address = uiBlocknum << SD_BLOCKSIZE_NBITS;
/* Wait until any old transfers are finished */
//SD_WaitNotBusy(ptSDCard);
/* Pack the address */
SD_Packarg(g_ucArgument, block_address);
if(SD_WriteCmd(ptSDCard, CMD24, CMD24_R, g_ucResponse, g_ucArgument) != SD_SUCCESS)
{
return SD_WRITE_CMD24_ERROR;
}
/* Check for an error, like a misaligned write */
if(g_ucResponse[0] != 0)
{
return SD_WRITE_RESPONSE_ERROR | (g_ucResponse[0])<<8;
}
/* Re-assert CS to continue the transfer */
SPI_SetCS(ptSDCard->eSPIId, ptSDCard->uiCSId);
/* Kick off the transfer by sending the first byte, the "start block"
* token */
SPI_PutChar(ptSDCard->eSPIId, ptSDCard->uiCSId, SD_TOK_WRITE_STARTBLOCK);
for(i = 0; i < SD_BLOCKSIZE / SD_DMA_WRITE_LEN; i++)
{
SPI_DmaWrite(ptSDCard->eSPIId, pucData + i * SD_DMA_WRITE_LEN);
}
SPI_PutChar(ptSDCard->eSPIId, ptSDCard->uiCSId, 0);
SPI_PutChar(ptSDCard->eSPIId, ptSDCard->uiCSId, 0); // 2 CRC bytes
data_response = (uint8)SPI_GetChar(ptSDCard->eSPIId); // get data response
result = SD_FAILURE; // default result is success.
if(data_response == SD_DRSP_CC_ERROR)
{
result = SD_WRITE_CRC_ERROR;
}
else if(data_response == SD_DRSP_WR_ERROR)
{
result = SD_WRITE_WR_ERROR;
}
else if(data_response == SD_DRSP_ACCEPT)
{
result = SD_SUCCESS;
}
/* 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 = SCI_TRUE;
if ((result1 = SD_WaitNotBusy( ptSDCard)) != SD_SUCCESS)
{
return result1;
}
SPI_SetCS(ptSDCard->eSPIId, CS_NONE);
return result;
}
/*****************************************************************************/
// Description: This function is used to write multiple block data.
// Author: Benjamin.Wang
// Note: The block size is fixed 512 Bytes.
/*****************************************************************************/
PUBLIC uint32 SD_WriteMultiBlock( // return status. SD_SUCCESS - success
SD_CARD_T* ptSDCard, // the card vector
uint32 uiStartBlocknum, // the start block
uint32 uiBlockCounts, // the writing counts
const uint8* pucData // the data pointer
)
{
uint32 i;
uint32 j;
uint32 block_address;
uint8 data_response;
uint32 result, result1;
if(!SD_RegisterVerify(ptSDCard)) //verify the SDCard vector
{
return SD_UNREGISTER;
}
if (g_sd_default_blocksize != SD_BLOCKSIZE)
{
if(SD_SetBlockLength(ptSDCard, SD_BLOCKSIZE) != SD_SUCCESS)
{
return SD_BLOCK_LENGTH_INVALID;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -