📄 sdmmc_spi.c
字号:
if( (R2 & R2_SPI_OUT_OF_RANGE)==R2_SPI_OUT_OF_RANGE) {
TRACE_DEBUG("R2_SPI_OUT_OF_RANGE/R2_SPI_CSD_OVERWRITE\n\r");
}
}
//------------------------------------------------------------------------------
/// Check SPI mode response 1.
/// Returns 0 if no error; Otherwise, returns error.
/// \param pResp Pointer to response token.
//------------------------------------------------------------------------------
static unsigned char SD_SPI_R1(unsigned char *pResp)
{
DecodeR1(*pResp);
if((*pResp & 0x7E) !=0) {
// An error occured
return SD_ERROR_NORESPONSE;
}
else {
return 0;
}
}
//------------------------------------------------------------------------------
/// Check SPI mode response 1b.
/// Returns 0 if no error; Otherwise, returns error.
/// \param pResp Pointer to response token.
//------------------------------------------------------------------------------
static unsigned char SD_SPI_R1b(unsigned char *pResp)
{
// A zero value indicates card is busy.
// A non-zero value indicates the card is ready for the next command.
if( (*pResp) == 0 ) {
TRACE_INFO("Card is busy\n\r");
}
DecodeR1(*(pResp+1));
if(((*(pResp+1)) & 0x7E) !=0) {
// An error occured
return SD_ERROR_NORESPONSE;
}
else {
return 0;
}
}
//------------------------------------------------------------------------------
/// Check SPI mode response 2.
/// Returns 0 if no error; Otherwise, returns error.
/// \param pResp Pointer to response token.
//------------------------------------------------------------------------------
static unsigned char SD_SPI_R2(unsigned char *pResp)
{
DecodeR1(*pResp);
DecodeR2(*(pResp+1));
if((( *pResp & 0x7e ) != 0) && (*(pResp+1) != 0)) {
return SD_ERROR_NORESPONSE;
}
else {
return 0;
}
}
//------------------------------------------------------------------------------
/// Check SPI mode response 3.
/// Returns 0 if no error; Otherwise, returns error.
/// \param pResp Pointer to response token.
//------------------------------------------------------------------------------
static unsigned char SD_SPI_R3(unsigned char *pResp, unsigned int *ocr)
{
// *pResp: bit 32-39: R1
if(( *pResp & 0x7e ) != 0) {
return SD_ERROR_NORESPONSE;
}
else {
// bit 0-31: OCR
*ocr = ((*(pResp+1) << 24) \
|(*(pResp+2) << 16) \
|(*(pResp+3) << 8) \
| *(pResp+4));
return 0;
}
}
//------------------------------------------------------------------------------
/// Check SPI mode response 7.
/// Returns 0 if no error; Otherwise, returns error.
/// \param pResp Pointer to response token.
//------------------------------------------------------------------------------
static unsigned char SD_SPI_R7(unsigned char *pResp, unsigned char *isSdhc)
{
*isSdhc = 0;
if(( *pResp & 0x7e ) != 0) {
return SD_ERROR_NORESPONSE;
}
else {
// *(pResp+4): bit 0- 7: check pattern
// *(pResp+3): bit 8-11: voltage accepted: 0x01: 2.7-3.6V
if ((*(pResp+3) == 0x1) && (*(pResp+4) == 0xAA)) {
*isSdhc = 1;
}
else {
*isSdhc = 0;
}
return 0;
}
}
//------------------------------------------------------------------------------
/// Initialization delay: The maximum of 1 msec, 74 clock cycles and supply ramp
/// up time.
/// Returns the command transfer result (see SendCommand).
/// \param pSd Pointer to a SdCard driver instance.
//------------------------------------------------------------------------------
static unsigned char Pon(SdCard *pSd)
{
SdCmd *pCommand = &(pSd->command);
unsigned int response;
unsigned char error;
TRACE_DEBUG("Pon()\n\r");
memset(pCommand, 0, sizeof(SdCmd));
// Fill command information
pCommand->cmd = AT91C_POWER_ON_INIT;
pCommand->resType = 1;
pCommand->pResp = &response;
// Set SD command state
pSd->state = SD_STATE_STBY;
// Send command
error = SendCommand(pSd);
if( error == 0 ) {
error = SD_SPI_R1((unsigned char *)&response);
}
return error;
}
//------------------------------------------------------------------------------
/// Resets all cards to idle state
/// Returns the command transfer result (see SendCommand).
/// \param pSd Pointer to a SdCard driver instance.
//------------------------------------------------------------------------------
static unsigned char Cmd0(SdCard *pSd)
{
SdCmd *pCommand = &(pSd->command);
unsigned int response;
unsigned char error;
TRACE_DEBUG("Cmd0()\n\r");
memset(pCommand, 0, sizeof(SdCmd));
// Fill command information
pCommand->cmd = AT91C_GO_IDLE_STATE_CMD;
pCommand->resType = 1;
pCommand->pResp = &response;
// Set SD command state
pSd->state = SD_STATE_STBY;
// send command
error = SendCommand(pSd);
error = SD_SPI_R1((unsigned char *)&response);
return error;
}
//------------------------------------------------------------------------------
/// MMC send operation condition command.
/// Sends host capacity support information and activates the card's
/// initialization process.
/// Returns the command transfer result (see SendCommand).
/// \param pSd Pointer to a SdCard driver instance.
//------------------------------------------------------------------------------
static unsigned char Cmd1(SdCard *pSd)
{
SdCmd *pCommand = &(pSd->command);
unsigned char error;
unsigned int response;
TRACE_DEBUG("Cmd1()\n\r");
memset(pCommand, 0, sizeof(SdCmd));
// Fill command information
pCommand->cmd = AT91C_MMC_SEND_OP_COND_CMD;
pCommand->arg = AT91C_MMC_HOST_VOLTAGE_RANGE;
pCommand->resType = 1;
pCommand->pResp = &response;
// Set SD command state
pSd->state = SD_STATE_STBY;
// send command
error = SendCommand(pSd);
if (error) {
return error;
}
error = SD_SPI_R1((unsigned char *)&response);
return error;
}
//------------------------------------------------------------------------------
/// Sends SD Memory Card interface
/// condition, which includes host supply
/// voltage information and asks the card
/// whether card supports voltage.
/// Returns 0 if successful; otherwise returns SD_ERROR_NORESPONSE if the card did
/// not answer the command, or SD_ERROR_DRIVER.
/// \param pSd Pointer to a SD card driver instance.
/// \param supplyVoltage Expected supply voltage.
//------------------------------------------------------------------------------
static unsigned char Cmd8(SdCard *pSd, unsigned char supplyVoltage)
{
SdCmd *pCommand = &(pSd->command);
unsigned int response[2];
unsigned char error;
unsigned char isSdhc;
TRACE_DEBUG("Cmd8()\n\r");
memset(pCommand, 0, sizeof(SdCmd));
// Fill command information
pCommand->cmd = AT91C_SEND_IF_COND;
pCommand->arg = (supplyVoltage << 8) | (0xAA);
pCommand->resType = 7;
pCommand->pResp = &response[0];
// Set SD command state
pSd->state = SD_STATE_STBY;
TRACE_DEBUG("supplyVoltage: 0x%x\n\r", supplyVoltage);
// Send command
error = SendCommand(pSd);
TRACE_DEBUG("SD_R7[0]: 0x%x\n\r", response[0]);
TRACE_DEBUG("SD_R7[1]: 0x%x\n\r", response[1]);
error = SD_SPI_R7((unsigned char *)&response, &isSdhc);
if( error == SD_ERROR_NORESPONSE ) {
TRACE_DEBUG("Cmd8 R7 error:%d \n\r", error);
return error;
}
else {
if(isSdhc == 1) {
TRACE_DEBUG("Cmd8 Ver 2.00 isSdhc:%d\n\r", isSdhc);
return 0;
}
else {
TRACE_DEBUG("Cmd8 Ver 1.X isSdhc:%d\n\r", isSdhc);
return error;
}
}
}
//------------------------------------------------------------------------------
/// Addressed card sends its card-specific
/// data (CSD) on the CMD line.
/// Returns the command transfer result (see SendCommand).
/// \param pSd Pointer to a SD card driver instance.
//------------------------------------------------------------------------------
static unsigned char Cmd9(SdCard *pSd)
{
SdCmd *pCommand = &(pSd->command);
unsigned char error;
unsigned int response = 0;
unsigned char csdData[16];
unsigned int i;
TRACE_DEBUG("Cmd9()\n\r");
memset(pCommand, 0, sizeof(SdCmd));
// Fill command information
pCommand->cmd = AT91C_SEND_CSD_CMD;
pCommand->resType = 1;
pCommand->blockSize = 16;
pCommand->pData = csdData;
pCommand->isRead = 1;
pCommand->pResp = &response;
// Set SD command state
pSd->state = SD_STATE_STBY;
// Send command
error = SendCommand(pSd);
// In SPI mode, reading CSD is the same as reading data.
for (i = 0; i < 4; i++) {
pSd->csd[i] = csdData[i*4] << 24 |
csdData[i*4+1] << 16 |
csdData[i*4+2] << 8 |
csdData[i*4+3];
}
error = SD_SPI_R1((unsigned char *)&response);
return error;
}
//------------------------------------------------------------------------------
/// Forces the card to stop transmission
/// \param pSd Pointer to a SD card driver instance.
/// \param pStatus Pointer to a status variable.
//------------------------------------------------------------------------------
static unsigned char Cmd12(SdCard *pSd)
{
SdCmd *pCommand = &(pSd->command);
unsigned char error;
unsigned int response;
TRACE_DEBUG("Cmd12()\n\r");
memset(pCommand, 0, sizeof(SdCmd));
// Fill command information
pCommand->cmd = AT91C_STOP_TRANSMISSION_CMD;
pCommand->conTrans = SPI_NEW_TRANSFER;
pCommand->resType = 1;
pCommand->pResp = &response;
// Set SD command state
pSd->state = SD_STATE_STBY;
// Send command
error = SendCommand(pSd);
//TRACE_DEBUG("cmd12 resp 0x%X\n\r",response);
error = SD_SPI_R1b((unsigned char *)&response);
return error;
}
//------------------------------------------------------------------------------
/// Addressed card sends its status register.
/// Returns the command transfer result (see SendCommand).
/// \param pSd Pointer to a SD card driver instance.
/// \param pStatus Pointer to a status variable.
//------------------------------------------------------------------------------
static unsigned char Cmd13(SdCard *pSd, unsigned int *pStatus)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -