Description
Source
Call Graph
Start Line: 1172
unsigned char SD_SPI_Init(SdCard *pSd, SdDriver *pSpi)
{
unsigned char isCCSet;
unsigned char error;
unsigned char cmd8Retries = 2;
unsigned char cmd1Retries = 1;
unsigned int pOCR;
// The command GO_IDLE_STATE (CMD0) is the software reset command and sets card into Idle State
// regardless of the current card state.
error = Cmd0(pSd);
if (error) {
TRACE_ERROR("Error during initialization (%d)\n\r", error);
return error;
}
// CMD8 is newly added in the Physical Layer Specification Version 2.00 to support multiple voltage
// ranges and used to check whether the card supports supplied voltage. The version 2.00 host shall
// issue CMD8 and verify voltage before card initialization.
// The host that does not support CMD8 shall supply high voltage range...
do {
error = Cmd8(pSd, 1);
}
while ((error == SD_ERROR_NORESPONSE) && (cmd8Retries-- > 0));
if (error == SD_ERROR_NORESPONSE) {
// No response : Ver2.00 or later SD Memory Card(voltage mismatch)
// or Ver1.X SD Memory Card
// or not SD Memory Card
TRACE_DEBUG("No response to Cmd8\n\r");
// CMD58 ? !
error = Cmd58(pSd, &pOCR);
if (error) {
TRACE_ERROR("Error during initialization (%d), 8\n\r", error);
return error;
}
// ACMD41 is a synchronization command used to negotiate the operation voltage range and to poll the
// cards until they are out of their power-up sequence.
error = Acmd41(pSd, 0, &isCCSet);
if (error) {
// Acmd41 failed : MMC card or unknown card
error = Cmd0(pSd);
if (error) {
TRACE_ERROR("Error during initialization (%d)\n\r", error);
return error;
}
do {
error = Cmd1(pSd);
}
while ((error) && (cmd1Retries-- > 0));
if (error) {
TRACE_ERROR("Error during initialization (%d)\n\r", error);
return error;
}
else {
pSd->cardType = CARD_MMC;
}
}
else {
if(isCCSet == 0) {
TRACE_DEBUG("CARD SD\n\r");
pSd->cardType = CARD_SD;
}
}
}
else if (!error) {
error = Cmd58(pSd, &pOCR);
if (error) {
TRACE_ERROR("Error during initialization (%d), 8\n\r", error);
return error;
}
// Valid response : Ver2.00 or later SD Memory Card
error = Acmd41(pSd, 1, &isCCSet);
if (error) {
TRACE_ERROR("Error during initialization (%d)\n\r", error);
return error;
}
error = Cmd58(pSd, &pOCR);
if (error) {
TRACE_ERROR("Error during initialization (%d), 8\n\r", error);
return error;
}
if (isCCSet) {
TRACE_DEBUG("CARD SDHC\n\r");
pSd->cardType = CARD_SDHC;
}
else {
TRACE_DEBUG("CARD SD\n\r");
pSd->cardType = CARD_SD;
}
}
else {
TRACE_ERROR("Error during initialization (%d)\n\r", error);
return error;
}
if (pSd->cardType != CARD_MMC) {
// The host issues CRC_ON_OFF (CMD59) to set data CRC on/off
// The host can turn the CRC option on and off using the CRC_ON_OFF command (CMD59).
// Host should enable CRC verification before issuing ACMD41.
error = Cmd59(pSd,0); // turn crc option OFF
if (error) {
TRACE_ERROR("Error during initialization (%d)\n\r, 59", error);
return error;
}
}
// The host issues SEND_CSD (CMD9) to obtain the Card Specific Data (CSD register),
// e.g. block length, card storage capacity, etc...
error = Cmd9(pSd);
if (error) {
TRACE_ERROR("Error during initialization (%d), 9\n\r", error);
return error;
}
return 0;
}