SD_SPI_Init
Default mainpageat91libmemoriessdmmcSD_SPI_Init
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;
}