📄 sd.c
字号:
SPI_SetBusClk(ptSDCard->eSPIId, ptSDCard->uiClockRate); // set spi bus clock to max speed
/* Adjust the block address to a linear address */
block_address = uiStartBlocknum << SD_BLOCKSIZE_NBITS;
/* Pack the address */
SD_Packarg(g_ucArgument, block_address);
if(SD_WriteCmd(ptSDCard, CMD25, CMD25_R, g_ucResponse, g_ucArgument) != SD_SUCCESS)
{
return SD_WRITEMULTI_CMD25_ERROR;
}
/* Check for an error, like a misaligned write */
if(g_ucResponse[0] != 0)
{
return SD_WRITEMULTI_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++)
{
/* Kick off the transfer by sending the first byte, the "start block"
* token */
SPI_PutChar(ptSDCard->eSPIId, ptSDCard->uiCSId, SD_TOK_WRITE_STARTBLOCK_M);
//sd card DMA write
for(i = 0; i < SD_BLOCKSIZE / SD_DMA_WRITE_LEN; i++)
{
SPI_DmaWrite(ptSDCard->eSPIId, pucData + j * SD_BLOCKSIZE + i * SD_DMA_WRITE_LEN);
}
/* Write 2 invalid CRC bytes*/
SPI_PutChar(ptSDCard->eSPIId, ptSDCard->uiCSId, 0);
SPI_PutChar(ptSDCard->eSPIId, ptSDCard->uiCSId, 0);
i = 0;
do
{
data_response = (uint8)SPI_GetChar(ptSDCard->eSPIId);
i++;
}
while((data_response == 0xFF) && i < ptSDCard->uiWriteTimeout);
if((data_response & MSK_TOK_DATAERROR) != MSK_TOK_DATAERROR)
{
/* 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_WRITEMULTI_DATA_RESPONSE_ERROR | data_response<<8;
}
result = SD_FAILURE; // default result is success.
if(data_response == SD_DRSP_CC_ERROR)
{
result = SD_WRITE_CRC_ERROR;
break;
}
else if(data_response == SD_DRSP_WR_ERROR)
{
result = SD_WRITE_WR_ERROR;
break;
}
else if(data_response == SD_DRSP_ACCEPT)
{
result = SD_SUCCESS;
}
else
{
return result;
}
ptSDCard->bBusyFlag = SCI_TRUE;
if ((result1 = SD_WaitNotBusy( ptSDCard)) != SD_SUCCESS)
{
return result1;
}
}
SPI_PutChar(ptSDCard->eSPIId, ptSDCard->uiCSId, SD_TOK_STOP_MULTI);
/* 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: Once the programming operation is completed, the host must check the
// results of the programming using the SEND_STATUS command(CMD13).
// Some errors(e.g., address out of range, write protect violation, etc.)are
// detected during programming only.
// Author: Benjamin.Wang
// Note:
/*****************************************************************************/
PUBLIC uint32 SD_SendStatus( // return status. SD_SUCCESS - success
SD_CARD_T* ptSDCard, // the card vector
uint8* pucStatus // the response status(2 bytes)
// Byte[0] - bit7: Always 0
// bit6: Parameter Error
// bit5: Address Error
// bit4: Erase Sequence Error
// bit3: Com CRC Error
// bit2: Illegal Command
// bit1: Erase Reset
// bit0:In Idle State
// Byte[1] - bit7: Out of Range, CSD_Overwrite
// bit6: Erase Param
// bit5: WP Violation
// bit4: Card ECC Failed
// bit3: CC Error
// bit2: Error
// bit1: WP Erase Skip, Lock/Unlock Cmd Failed
// bit0: Card is Locked
)
{
if(!SD_RegisterVerify(ptSDCard)) //verify the SDCard vector
{
return SD_UNREGISTER;
}
SPI_SetBusClk(ptSDCard->eSPIId, ptSDCard->uiClockRate); // set spi bus clock to the setting speed
/* Pack the arguments */
SD_Packarg(g_ucArgument, 0);
/* Wait until any old transfers are finished */
//SD_WaitNotBusy(ptSDCard);
/* Need to add size checking */
if(SD_WriteCmd(ptSDCard, CMD13, CMD13_R, g_ucResponse, g_ucArgument) != SD_SUCCESS)
{
return SD_SENDSTATUS_CMD13_ERROR;
}
/* Check for an error, like a misaligned read */
if(g_ucResponse[1] != 0)
{
return SD_SENDSTATUS_RESPONSE_ERROR | (g_ucResponse[1])<<8;
}
pucStatus[0] = g_ucResponse[1];
pucStatus[1] = g_ucResponse[0];
return SD_SUCCESS;
}
/*****************************************************************************/
// Description: In multiple-block write operations, the stop transmission is done by sending,
// at the beginning of the next block, a Stop Tran token, instead of a Start Block
// token. In case of Write Error indication(on the data response)the host shall use
// SEND_NUM_WR_BLOCKS(ACMD22) in order to get the number of well written
// write blocks.
// Author: Benjamin.Wang
// Note:
/*****************************************************************************/
PUBLIC uint32 SD_SendNumWrBlocks( // return status. SD_SUCCESS - success
SD_CARD_T* ptSDCard, // the Card Vector
uint8* pucData // the number of well written write blocks
)
{
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 the setting speed
/* Pack the arguments */
SD_Packarg(g_ucArgument, 0);
/* Wait until any old transfers are finished */
//SD_WaitNotBusy(ptSDCard);
/* Need to add size checking */
if(SD_WriteCmd(ptSDCard, CMD55, CMD55_R, g_ucResponse, g_ucArgument) != SD_SUCCESS)
{
return SD_SENDNUMWRBLOCKS_CMD55_ERROR;
}
/* Check for an error, like a misaligned read */
if(g_ucResponse[0] != 0)
{
return SD_SENDNUMWRBLOCKS_RESPONSE_ERROR1 | (g_ucResponse[0])<<8;
}
/* Need to add size checking */
if(SD_WriteCmd(ptSDCard, ACMD22, ACMD22_R, g_ucResponse, g_ucArgument) != SD_SUCCESS)
{
return SD_SENDNUMWRBLOCKS_CMD22_ERROR;
}
/* Check for an error, like a misaligned read */
if(g_ucResponse[0] != 0)
{
return SD_SENDNUMWRBLOCKS_RESPONSE_ERROR2 | (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 & 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_SENDNUMWRBLOCKS_TOKEN_ERROR | tmp<<8;
}
for(i = 0; i < 4 + 2; i++) //32bits + CRC data block
{
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 set the read block length. The maximum block length
// is 512 bytes. Block lengths can be any number between 1 and 512 bytes. But
// in write mode, the only valid block length is 512 bytes.
// Author: Benjamin.Wang
// Note: At present, the sdcard driver only supports the card whose capability
// is less than or equal to 2GB.
/*****************************************************************************/
PUBLIC uint32 SD_SetBlockLength( // return status. SD_SUCCESS - success
SD_CARD_T* ptSDCard, // the card vector
uint32 uiBlockLength // the block length
)
{
if (uiBlockLength > 512)
{
return SD_SETBLOCKLENGTH_PARAM_ERROR;
}
if(!SD_RegisterVerify(ptSDCard)) //verify the SDCard vector
{
return SD_UNREGISTER;
}
SPI_SetBusClk(ptSDCard->eSPIId, ptSDCard->uiClockRate); // set spi bus clock to the setting speed
/* Pack the arguments */
SD_Packarg(g_ucArgument, uiBlockLength);
/* Wait until any old transfers are finished */
//SD_WaitNotBusy(ptSDCard);
/* Need to add size checking */
if(SD_WriteCmd(ptSDCard, CMD16, CMD16_R, g_ucResponse, g_ucArgument) != SD_SUCCESS)
{
return SD_SETBLOCKLENGTH_CMD16_ERROR;
}
/* Check for an error, like a misaligned read */
if(g_ucResponse[0] != 0)
{
return SD_SETBLOCKLENGTH_RESPONSE_ERROR | (g_ucResponse[0])<<8;
}
g_sd_default_blocksize = uiBlockLength;
return SD_SUCCESS;
}
/*****************************************************************************/
// Description: This function is used to erase data.
// Author: Benjamin.Wang
// Note:
/*****************************************************************************/
PUBLIC uint32 SD_Erase( // return status. SD_SUCCESS - success
SD_CARD_T* ptSDCard, // the card vector
uint32 uiStartBlock, // the start block
uint32 uiEndBlock // the end block
)
{
uint32 start_block_address;
uint32 end_block_address;
uint32 result;
if(!SD_RegisterVerify(ptSDCard)) //verify the SDCard vector
{
return SD_UNREGISTER;
}
SPI_SetBusClk(ptSDCard->eSPIId, ptSDCard->uiClockRate); // set spi bus clock to max speed
/* Adjust the block address to a linear address */
start_block_address = uiStartBlock << SD_BLOCKSIZE_NBITS;
/* Pack the address */
SD_Packarg(g_ucArgument, start_block_address);
if(SD_WriteCmd(ptSDCard, CMD32, CMD32_R, g_ucResponse, g_ucArgument) != SD_SUCCESS)
{
return SD_ERASE_CMD32_ERROR;
}
/* Check for an error, like a misaligned write */
if(g_ucResponse[0] != 0)
{
return SD_ERASE_RESPONSE_ERROR1 | (g_ucResponse[0])<<8;
}
/* Adjust the end block address to a linear address */
end_block_address = ((uiEndBlock + 1) << SD_BLOCKSIZE_NBITS) - 1;
/* Pack the address */
SD_Packarg(g_ucArgument, end_block_address);
if(SD_WriteCmd(ptSDCard, CMD33, CMD33_R, g_ucResponse, g_ucArgument) != SD_SUCCESS)
{
return SD_ERASE_CMD33_ERROR;
}
/* Check for an error, like a misaligned write */
if(g_ucResponse[0] != 0)
{
return SD_ERASE_RESPONSE_ERROR2 | (g_ucResponse[0])<<8;
}
/* Pack the address */
SD_Packarg(g_ucArgument, 0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -