SD_MCI_Init函数做的工作是初始化SD卡。有可能是SD卡或是MMC卡。
//------------------------------------------------------------------------------ /// Run the SDcard SD Mode initialization sequence. This function runs the 根据SD协议初始化SD卡(或MMC卡),此函数完成后进入数据传输模式 /// initialisation procedure and the identification process, then it sets the /// SD card in transfer state to set the block length and the bus width. /// Returns 0 if successful; otherwise returns an SD_ERROR code. /// \param pSd Pointer to a SD card driver instance. /// \param pSdDriver Pointer to SD driver already initialized //------------------------------------------------------------------------------ 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... 检查是否支持CMD8命令 TRACE_DEBUG("Cmd8()\n\r"); do { error = Cmd8(pSd, 1); } while ((error == SD_ERROR_NORESPONSE) && (cmd8Retries-- > 0)); if (error == SD_ERROR_NORESPONSE) { //不支持CMD8命令,所以SD卡的版本是2.00以下,或者它不是SD卡或MMC卡。 // 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); //发送ACMD41命令 if (error) { // Acmd41 failed : MMC card or unknown card 不支持ACMD41,它可能是MMC卡,下面先复位再发送CMD1命令偿试初始化MMC卡 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) { //发送CMD8命令成功,那么它是版本2.00以上的SD卡。 // 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); //获取CID寄存器的内容。 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 选择当前的SD卡或MMC卡,使它进入数据传输模式。 // 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) { //如果是SD卡,那么设置成4位数据线模式。 // 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; }