Description
Source
Call Graph
Start Line: 1157
unsigned char SD_MCI_Init(SdCard *pSd, SdDriver *pSdDriver)
{
unsigned int sdCid[4];
unsigned char isCCSet;
unsigned char error;
unsigned int status;
unsigned char cmd8Retries = 2;
unsigned char cmd1Retries = 100;
// 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...
TRACE_DEBUG("Cmd8()\n\r");
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");
// 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 {
TRACE_DEBUG("CARD MMC\n\r");
pSd->cardType = CARD_MMC;
}
}
else {
if(isCCSet == 0) {
TRACE_DEBUG("CARD SD\n\r");
pSd->cardType = CARD_SD;
}
}
}
else if (!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;
}
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;
}
// The host then issues the command ALL_SEND_CID (CMD2) to the card to get its unique card identification (CID) number.
// Card that is unidentified (i.e. which is in Ready State) sends its CID number as the response (on the CMD line).
error = Cmd2(pSd, sdCid);
if (error) {
TRACE_ERROR("Error during initialization (%d)\n\r", error);
return error;
}
// Thereafter, the host issues CMD3 (SEND_RELATIVE_ADDR) asks the
// card to publish a new relative card address (RCA), which is shorter than CID and which is used to
// address the card in the future data transfer mode. Once the RCA is received the card state changes to
// the Stand-by State. At this point, if the host wants to assign another RCA number, it can ask the card to
// publish a new number by sending another CMD3 command to the card. The last published RCA is the
// actual RCA number of the card.
error = Cmd3(pSd);
if (error) {
TRACE_ERROR("Error during initialization (%d)\n\r", 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)\n\r", error);
return error;
}
// At this stage the Initialization and identification process is achieved
// The SD card is supposed to be in Stand-by State
do {
error = Cmd13(pSd, &status);
if (error) {
TRACE_ERROR("Error during initialization (%d)\n\r", error);
return error;
}
}
while ((status & STATUS_READY_FOR_DATA) == 0);
// If the 4 bit bus transfer is supported switch to this mode
// Select the current SD, goto transfer state
error = Cmd7(pSd, pSd->cardAddress);
if (error) {
TRACE_ERROR("Error during initialization (%d)\n\r", error);
return error;
}
if (pSd->cardType != CARD_MMC) {
// Switch to 4 bits bus width (All SD Card shall support 1-bit, 4 bitswidth
error = Acmd6(pSd, 4);
if (error) {
TRACE_ERROR("Error during initialization (%d)\n\r", error);
return error;
}
}
else {
MCI_SetBusWidth((Mci *)pSdDriver, MCI_SDCBUS_1BIT);
}
return 0;
}