|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
//------------------------------------------------------------------------------
|
|
|
// send command and return error code. Return zero for OK
|
|
|
// send command and return error code. Return zero for OK
|
|
|
uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg)
|
|
|
uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg)
|
|
|
{
|
|
|
{
|
|
|
// select card
|
|
|
|
|
|
chipSelectLow();
|
|
|
|
|
|
|
|
|
|
|
|
// wait up to 300 ms if busy
|
|
|
// wait up to 300 ms if busy
|
|
|
waitNotBusy(300);
|
|
|
waitNotBusy(300);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
}
|
|
|
// check SD version
|
|
|
// check SD version
|
|
|
if ((cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND)) {
|
|
|
if ((cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND)) {
|
|
|
type(SD_CARD_TYPE_SD1);
|
|
|
|
|
|
|
|
|
type_ = SD_CARD_TYPE_SD1;
|
|
|
} else {
|
|
|
} else {
|
|
|
// only need last byte of r7 response
|
|
|
// only need last byte of r7 response
|
|
|
for (uint8_t i = 0; i < 4; i++) status_ = spiRec();
|
|
|
for (uint8_t i = 0; i < 4; i++) status_ = spiRec();
|
|
|
if (status_ != 0XAA) {
|
|
|
if (status_ != 0XAA) {
|
|
|
goto fail; // SD_CARD_ERROR_CMD8
|
|
|
goto fail; // SD_CARD_ERROR_CMD8
|
|
|
}
|
|
|
}
|
|
|
type(SD_CARD_TYPE_SD2);
|
|
|
|
|
|
|
|
|
type_ = SD_CARD_TYPE_SD2;
|
|
|
}
|
|
|
}
|
|
|
// initialize card and send host supports SDHC if SD2
|
|
|
// initialize card and send host supports SDHC if SD2
|
|
|
arg = type() == SD_CARD_TYPE_SD2 ? 0X40000000 : 0;
|
|
|
|
|
|
|
|
|
arg = (type_ == SD_CARD_TYPE_SD2) ? 0X40000000 : 0;
|
|
|
|
|
|
|
|
|
while ((status_ = cardAcmd(ACMD41, arg)) != R1_READY_STATE) {
|
|
|
while ((status_ = cardAcmd(ACMD41, arg)) != R1_READY_STATE) {
|
|
|
// check for timeout
|
|
|
// check for timeout
|
|
|
|
|
|
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
// if SD2 read OCR register to check for SDHC card
|
|
|
// if SD2 read OCR register to check for SDHC card
|
|
|
if (type() == SD_CARD_TYPE_SD2) {
|
|
|
|
|
|
|
|
|
if (type_ == SD_CARD_TYPE_SD2) {
|
|
|
if (cardCommand(CMD58, 0)) {
|
|
|
if (cardCommand(CMD58, 0)) {
|
|
|
goto fail; // SD_CARD_ERROR_CMD58
|
|
|
goto fail; // SD_CARD_ERROR_CMD58
|
|
|
}
|
|
|
}
|
|
|
if ((spiRec() & 0XC0) == 0XC0) type(SD_CARD_TYPE_SDHC);
|
|
|
|
|
|
|
|
|
if ((spiRec() & 0XC0) == 0XC0) type_ = SD_CARD_TYPE_SDHC;
|
|
|
// discard rest of ocr - contains allowed voltage range
|
|
|
// discard rest of ocr - contains allowed voltage range
|
|
|
for (uint8_t i = 0; i < 3; i++) spiRec();
|
|
|
for (uint8_t i = 0; i < 3; i++) spiRec();
|
|
|
}
|
|
|
}
|
|
|
chipSelectHigh();
|
|
|
chipSelectHigh();
|
|
|
|
|
|
|
|
|
return setSckRate(sckRateID);
|
|
|
return setSckRate(sckRateID);
|
|
|
|
|
|
|
|
|
fail:
|
|
|
|
|
|
|
|
|
fail:
|
|
|
chipSelectHigh();
|
|
|
chipSelectHigh();
|
|
|
return false;
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
uint8_t Sd2Card::readBlock(uint32_t block, uint8_t* dst)
|
|
|
uint8_t Sd2Card::readBlock(uint32_t block, uint8_t* dst)
|
|
|
{
|
|
|
{
|
|
|
// use address if not SDHC card
|
|
|
// use address if not SDHC card
|
|
|
if (type() != SD_CARD_TYPE_SDHC) block <<= 9;
|
|
|
|
|
|
|
|
|
if (type_ != SD_CARD_TYPE_SDHC) block <<= 9;
|
|
|
|
|
|
chipSelectLow();
|
|
|
if (cardCommand(CMD17, block)) {
|
|
|
if (cardCommand(CMD17, block)) {
|
|
|
goto fail; // SD_CARD_ERROR_CMD17
|
|
|
goto fail; // SD_CARD_ERROR_CMD17
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
return false;
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
//------------------------------------------------------------------------------
|
|
|
//------------------------------------------------------------------------------
|
|
|
/** read CID or CSR register */
|
|
|
|
|
|
uint8_t Sd2Card::readRegister(uint8_t cmd, void* buf) {
|
|
|
|
|
|
uint8_t* dst = reinterpret_cast<uint8_t*>(buf);
|
|
|
|
|
|
if (cardCommand(cmd, 0)) {
|
|
|
|
|
|
goto fail; // SD_CARD_ERROR_READ_REG
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!waitStartBlock()) goto fail;
|
|
|
|
|
|
// transfer data
|
|
|
|
|
|
for (uint16_t i = 0; i < 16; i++) dst[i] = spiRec();
|
|
|
|
|
|
spiRec(); // get first crc byte
|
|
|
|
|
|
spiRec(); // get second crc byte
|
|
|
|
|
|
chipSelectHigh();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
|
|
fail:
|
|
|
|
|
|
chipSelectHigh();
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
/**
|
|
|
/**
|
|
|
* Set the SPI clock rate.
|
|
|
* Set the SPI clock rate.
|
|
|
*
|
|
|
*
|
|
|
|
|
|
|
|
|
#endif // SD_PROTECT_BLOCK_ZERO
|
|
|
#endif // SD_PROTECT_BLOCK_ZERO
|
|
|
|
|
|
|
|
|
// use address if not SDHC card
|
|
|
// use address if not SDHC card
|
|
|
if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;
|
|
|
|
|
|
|
|
|
if (type_ != SD_CARD_TYPE_SDHC) blockNumber <<= 9;
|
|
|
|
|
|
chipSelectLow();
|
|
|
if (cardCommand(CMD24, blockNumber)) {
|
|
|
if (cardCommand(CMD24, blockNumber)) {
|
|
|
goto fail; // SD_CARD_ERROR_CMD24
|
|
|
goto fail; // SD_CARD_ERROR_CMD24
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
status_ = spiRec();
|
|
|
status_ = spiRec();
|
|
|
if ((status_ & DATA_RES_MASK) != DATA_RES_ACCEPTED) {
|
|
|
if ((status_ & DATA_RES_MASK) != DATA_RES_ACCEPTED) {
|
|
|
chipSelectHigh();
|
|
|
|
|
|
return false; // SD_CARD_ERROR_WRITE
|
|
|
return false; // SD_CARD_ERROR_WRITE
|
|
|
}
|
|
|
}
|
|
|
return true;
|
|
|
return true;
|