This commit is contained in:
@@ -27,14 +27,11 @@
|
||||
class Timeout {
|
||||
public:
|
||||
Timeout() {}
|
||||
explicit Timeout(uint16_t ms) {set(ms);}
|
||||
uint16_t millis16() {return millis();}
|
||||
void set(uint16_t ms) {
|
||||
m_endTime = ms + millis16();
|
||||
}
|
||||
bool timedOut() {
|
||||
return (int16_t)(m_endTime - millis16()) < 0;
|
||||
}
|
||||
explicit Timeout(uint16_t ms) { set(ms); }
|
||||
uint16_t millis16() { return millis(); }
|
||||
void set(uint16_t ms) { m_endTime = ms + millis16(); }
|
||||
bool timedOut() { return (int16_t)(m_endTime - millis16()) < 0; }
|
||||
|
||||
private:
|
||||
uint16_t m_endTime;
|
||||
};
|
||||
@@ -77,48 +74,44 @@ static uint16_t CRC_CCITT(const uint8_t* data, size_t n) {
|
||||
// uses the x^16,x^12,x^5,x^1 polynomial.
|
||||
#ifdef __AVR__
|
||||
static const uint16_t crctab[] PROGMEM = {
|
||||
#else // __AVR__
|
||||
#else // __AVR__
|
||||
static const uint16_t crctab[] = {
|
||||
#endif // __AVR__
|
||||
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
|
||||
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
|
||||
0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
|
||||
0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
|
||||
0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
|
||||
0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
|
||||
0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
|
||||
0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
|
||||
0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
|
||||
0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
|
||||
0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
|
||||
0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
|
||||
0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
|
||||
0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
|
||||
0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
|
||||
0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
|
||||
0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
|
||||
0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
|
||||
0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
|
||||
0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
|
||||
0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
|
||||
0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
|
||||
0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
|
||||
0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
|
||||
0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
|
||||
0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
|
||||
0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
|
||||
0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
|
||||
0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
|
||||
0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
|
||||
0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
|
||||
0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
|
||||
};
|
||||
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x8108,
|
||||
0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 0x1231, 0x0210,
|
||||
0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 0x9339, 0x8318, 0xB37B,
|
||||
0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, 0x2462, 0x3443, 0x0420, 0x1401,
|
||||
0x64E6, 0x74C7, 0x44A4, 0x5485, 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE,
|
||||
0xF5CF, 0xC5AC, 0xD58D, 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6,
|
||||
0x5695, 0x46B4, 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D,
|
||||
0xC7BC, 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
|
||||
0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, 0x5AF5,
|
||||
0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, 0xDBFD, 0xCBDC,
|
||||
0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, 0x6CA6, 0x7C87, 0x4CE4,
|
||||
0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD,
|
||||
0xAD2A, 0xBD0B, 0x8D68, 0x9D49, 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13,
|
||||
0x2E32, 0x1E51, 0x0E70, 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A,
|
||||
0x9F59, 0x8F78, 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E,
|
||||
0xE16F, 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
|
||||
0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, 0x02B1,
|
||||
0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, 0xB5EA, 0xA5CB,
|
||||
0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, 0x34E2, 0x24C3, 0x14A0,
|
||||
0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xA7DB, 0xB7FA, 0x8799, 0x97B8,
|
||||
0xE75F, 0xF77E, 0xC71D, 0xD73C, 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657,
|
||||
0x7676, 0x4615, 0x5634, 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9,
|
||||
0xB98A, 0xA9AB, 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882,
|
||||
0x28A3, 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
|
||||
0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, 0xFD2E,
|
||||
0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 0x7C26, 0x6C07,
|
||||
0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, 0xEF1F, 0xFF3E, 0xCF5D,
|
||||
0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, 0x6E17, 0x7E36, 0x4E55, 0x5E74,
|
||||
0x2E93, 0x3EB2, 0x0ED1, 0x1EF0};
|
||||
static uint16_t CRC_CCITT(const uint8_t* data, size_t n) {
|
||||
uint16_t crc = 0;
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
#ifdef __AVR__
|
||||
crc = pgm_read_word(&crctab[(crc >> 8 ^ data[i]) & 0XFF]) ^ (crc << 8);
|
||||
#else // __AVR__
|
||||
#else // __AVR__
|
||||
crc = crctab[(crc >> 8 ^ data[i]) & 0XFF] ^ (crc << 8);
|
||||
#endif // __AVR__
|
||||
}
|
||||
@@ -131,10 +124,9 @@ static uint16_t CRC_CCITT(const uint8_t* data, size_t n) {
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::begin(SdSpiConfig spiConfig) {
|
||||
Timeout timeout;
|
||||
m_spiActive = false;
|
||||
m_beginCalled = false;
|
||||
// Restore state to creator.
|
||||
initSharedSpiCard();
|
||||
m_errorCode = SD_CARD_ERROR_NONE;
|
||||
m_type = 0;
|
||||
m_csPin = spiConfig.csPin;
|
||||
#if SPI_DRIVER_SELECT >= 2
|
||||
m_spiDriverPtr = spiConfig.spiPort;
|
||||
@@ -145,32 +137,28 @@ bool SharedSpiCard::begin(SdSpiConfig spiConfig) {
|
||||
#endif // SPI_DRIVER_SELECT
|
||||
sdCsInit(m_csPin);
|
||||
spiUnselect();
|
||||
spiSetSckSpeed(1000UL*SD_MAX_INIT_RATE_KHZ);
|
||||
spiSetSckSpeed(1000UL * SD_MAX_INIT_RATE_KHZ);
|
||||
spiBegin(spiConfig);
|
||||
m_beginCalled = true;
|
||||
uint32_t arg;
|
||||
m_state = IDLE_STATE;
|
||||
spiStart();
|
||||
|
||||
// must supply min of 74 clock cycles with CS high.
|
||||
spiUnselect();
|
||||
for (uint8_t i = 0; i < 10; i++) {
|
||||
spiSend(0XFF);
|
||||
spiReceive();
|
||||
}
|
||||
spiSelect();
|
||||
// command to go idle in SPI mode
|
||||
for (uint8_t i = 1;; i++) {
|
||||
timeout.set(SD_INIT_TIMEOUT);
|
||||
while (true) {
|
||||
// command to go idle in SPI mode
|
||||
if (cardCommand(CMD0, 0) == R1_IDLE_STATE) {
|
||||
break;
|
||||
}
|
||||
if (i == SD_CMD0_RETRY) {
|
||||
if (timeout.timedOut()) {
|
||||
error(SD_CARD_ERROR_CMD0);
|
||||
goto fail;
|
||||
}
|
||||
// Force any active transfer to end for an already initialized card.
|
||||
for (uint8_t j = 0; j < 0XFF; j++) {
|
||||
spiSend(0XFF);
|
||||
}
|
||||
}
|
||||
#if USE_SD_CRC
|
||||
if (cardCommand(CMD59, 1) != R1_IDLE_STATE) {
|
||||
@@ -179,21 +167,26 @@ bool SharedSpiCard::begin(SdSpiConfig spiConfig) {
|
||||
}
|
||||
#endif // USE_SD_CRC
|
||||
// check SD version
|
||||
if (!(cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND)) {
|
||||
type(SD_CARD_TYPE_SD2);
|
||||
while (true) {
|
||||
if (cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND) {
|
||||
type(SD_CARD_TYPE_SD1);
|
||||
break;
|
||||
}
|
||||
// Skip first three bytes.
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
m_status = spiReceive();
|
||||
}
|
||||
if (m_status != 0XAA) {
|
||||
if (m_status == 0XAA) {
|
||||
type(SD_CARD_TYPE_SD2);
|
||||
break;
|
||||
}
|
||||
if (timeout.timedOut()) {
|
||||
error(SD_CARD_ERROR_CMD8);
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
type(SD_CARD_TYPE_SD1);
|
||||
}
|
||||
// initialize card and send host supports SDHC if SD2
|
||||
arg = type() == SD_CARD_TYPE_SD2 ? 0X40000000 : 0;
|
||||
timeout.set(SD_INIT_TIMEOUT);
|
||||
while (cardAcmd(ACMD41, arg) != R1_READY_STATE) {
|
||||
// check for timeout
|
||||
if (timeout.timedOut()) {
|
||||
@@ -201,7 +194,6 @@ bool SharedSpiCard::begin(SdSpiConfig spiConfig) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
// if SD2 read OCR register to check for SDHC card
|
||||
if (type() == SD_CARD_TYPE_SD2) {
|
||||
if (cardCommand(CMD58, 0)) {
|
||||
@@ -220,7 +212,7 @@ bool SharedSpiCard::begin(SdSpiConfig spiConfig) {
|
||||
spiSetSckSpeed(spiConfig.maxSck);
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
@@ -236,7 +228,7 @@ bool SharedSpiCard::cardCMD6(uint32_t arg, uint8_t* status) {
|
||||
spiStop();
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
@@ -267,7 +259,7 @@ uint8_t SharedSpiCard::cardCommand(uint8_t cmd, uint32_t arg) {
|
||||
|
||||
// send message
|
||||
spiSend(buf, 6);
|
||||
#else // USE_SD_CRC
|
||||
#else // USE_SD_CRC
|
||||
// send command
|
||||
spiSend(cmd | 0x40);
|
||||
|
||||
@@ -285,7 +277,7 @@ uint8_t SharedSpiCard::cardCommand(uint8_t cmd, uint32_t arg) {
|
||||
spiReceive();
|
||||
|
||||
// there are 1-8 fill bytes before response. fill bytes should be 0XFF.
|
||||
uint16_t n = 0;
|
||||
uint8_t n = 0;
|
||||
do {
|
||||
m_status = spiReceive();
|
||||
} while (m_status & 0X80 && ++n < 10);
|
||||
@@ -294,7 +286,7 @@ uint8_t SharedSpiCard::cardCommand(uint8_t cmd, uint32_t arg) {
|
||||
//------------------------------------------------------------------------------
|
||||
void SharedSpiCard::end() {
|
||||
if (m_beginCalled) {
|
||||
spiStop();
|
||||
syncDevice();
|
||||
spiEnd();
|
||||
m_beginCalled = false;
|
||||
}
|
||||
@@ -319,9 +311,8 @@ bool SharedSpiCard::erase(uint32_t firstSector, uint32_t lastSector) {
|
||||
firstSector <<= 9;
|
||||
lastSector <<= 9;
|
||||
}
|
||||
if (cardCommand(CMD32, firstSector)
|
||||
|| cardCommand(CMD33, lastSector)
|
||||
|| cardCommand(CMD38, 0)) {
|
||||
if (cardCommand(CMD32, firstSector) || cardCommand(CMD33, lastSector) ||
|
||||
cardCommand(CMD38, 0)) {
|
||||
error(SD_CARD_ERROR_ERASE);
|
||||
goto fail;
|
||||
}
|
||||
@@ -332,7 +323,7 @@ bool SharedSpiCard::erase(uint32_t firstSector, uint32_t lastSector) {
|
||||
spiStop();
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
@@ -357,9 +348,7 @@ bool SharedSpiCard::isBusy() {
|
||||
return rtn;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::readData(uint8_t* dst) {
|
||||
return readData(dst, 512);
|
||||
}
|
||||
bool SharedSpiCard::readData(uint8_t* dst) { return readData(dst, 512); }
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::readData(uint8_t* dst, size_t count) {
|
||||
#if USE_SD_CRC
|
||||
@@ -391,14 +380,14 @@ bool SharedSpiCard::readData(uint8_t* dst, size_t count) {
|
||||
error(SD_CARD_ERROR_READ_CRC);
|
||||
goto fail;
|
||||
}
|
||||
#else // USE_SD_CRC
|
||||
#else // USE_SD_CRC
|
||||
// discard crc
|
||||
spiReceive();
|
||||
spiReceive();
|
||||
#endif // USE_SD_CRC
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
@@ -412,14 +401,14 @@ bool SharedSpiCard::readOCR(uint32_t* ocr) {
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
p[3 - i] = spiReceive();
|
||||
#else // __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
#else // __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
p[i] = spiReceive();
|
||||
#endif // __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
}
|
||||
spiStop();
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
@@ -437,7 +426,7 @@ bool SharedSpiCard::readRegister(uint8_t cmd, void* buf) {
|
||||
spiStop();
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
@@ -454,7 +443,7 @@ bool SharedSpiCard::readSCR(scr_t* scr) {
|
||||
spiStop();
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
@@ -474,7 +463,7 @@ bool SharedSpiCard::readSector(uint32_t sector, uint8_t* dst) {
|
||||
spiStop();
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
@@ -489,7 +478,7 @@ bool SharedSpiCard::readSectors(uint32_t sector, uint8_t* dst, size_t ns) {
|
||||
}
|
||||
}
|
||||
return readStop();
|
||||
fail:
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -504,25 +493,25 @@ bool SharedSpiCard::readStart(uint32_t sector) {
|
||||
m_state = READ_STATE;
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::readStatus(SdStatus* status) {
|
||||
uint8_t* dst = reinterpret_cast<uint8_t*>(status);
|
||||
bool SharedSpiCard::readSDS(sds_t* sds) {
|
||||
uint8_t* dst = reinterpret_cast<uint8_t*>(sds);
|
||||
// retrun is R2 so read extra status byte.
|
||||
if (cardAcmd(ACMD13, 0) || spiReceive()) {
|
||||
error(SD_CARD_ERROR_ACMD13);
|
||||
goto fail;
|
||||
}
|
||||
if (!readData(dst, 64)) {
|
||||
if (!readData(dst, sizeof(sds_t))) {
|
||||
goto fail;
|
||||
}
|
||||
spiStop();
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
@@ -536,7 +525,7 @@ bool SharedSpiCard::readStop() {
|
||||
spiStop();
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
@@ -547,6 +536,7 @@ uint32_t SharedSpiCard::sectorCount() {
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void SharedSpiCard::spiStart() {
|
||||
SPI_ASSERT_NOT_ACTIVE;
|
||||
if (!m_spiActive) {
|
||||
spiActivate();
|
||||
m_spiActive = true;
|
||||
@@ -557,6 +547,7 @@ void SharedSpiCard::spiStart() {
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void SharedSpiCard::spiStop() {
|
||||
SPI_ASSERT_ACTIVE;
|
||||
if (m_spiActive) {
|
||||
spiUnselect();
|
||||
// Insure MISO goes to low Z.
|
||||
@@ -597,7 +588,7 @@ bool SharedSpiCard::writeData(const uint8_t* src) {
|
||||
}
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
@@ -606,7 +597,7 @@ bool SharedSpiCard::writeData(const uint8_t* src) {
|
||||
bool SharedSpiCard::writeData(uint8_t token, const uint8_t* src) {
|
||||
#if USE_SD_CRC
|
||||
uint16_t crc = CRC_CCITT(src, 512);
|
||||
#else // USE_SD_CRC
|
||||
#else // USE_SD_CRC
|
||||
uint16_t crc = 0XFFFF;
|
||||
#endif // USE_SD_CRC
|
||||
spiSend(token);
|
||||
@@ -621,7 +612,7 @@ bool SharedSpiCard::writeData(uint8_t token, const uint8_t* src) {
|
||||
}
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
@@ -655,13 +646,13 @@ bool SharedSpiCard::writeSector(uint32_t sector, const uint8_t* src) {
|
||||
spiStop();
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::writeSectors(uint32_t sector,
|
||||
const uint8_t* src, size_t ns) {
|
||||
bool SharedSpiCard::writeSectors(uint32_t sector, const uint8_t* src,
|
||||
size_t ns) {
|
||||
if (!writeStart(sector)) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -672,7 +663,7 @@ bool SharedSpiCard::writeSectors(uint32_t sector,
|
||||
}
|
||||
return writeStop();
|
||||
|
||||
fail:
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
@@ -689,7 +680,7 @@ bool SharedSpiCard::writeStart(uint32_t sector) {
|
||||
m_state = WRITE_STATE;
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
@@ -703,7 +694,7 @@ bool SharedSpiCard::writeStop() {
|
||||
m_state = IDLE_STATE;
|
||||
return true;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
error(SD_CARD_ERROR_STOP_TRAN);
|
||||
spiStop();
|
||||
return false;
|
||||
@@ -721,8 +712,7 @@ bool DedicatedSpiCard::readSector(uint32_t sector, uint8_t* dst) {
|
||||
return readSectors(sector, dst, 1);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool DedicatedSpiCard::readSectors(
|
||||
uint32_t sector, uint8_t* dst, size_t ns) {
|
||||
bool DedicatedSpiCard::readSectors(uint32_t sector, uint8_t* dst, size_t ns) {
|
||||
if (sdState() != READ_STATE || sector != m_curSector) {
|
||||
if (!readStart(sector)) {
|
||||
goto fail;
|
||||
@@ -737,7 +727,7 @@ bool DedicatedSpiCard::readSectors(
|
||||
m_curSector += ns;
|
||||
return m_dedicatedSpi ? true : readStop();
|
||||
|
||||
fail:
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -756,8 +746,8 @@ bool DedicatedSpiCard::writeSector(uint32_t sector, const uint8_t* src) {
|
||||
return SharedSpiCard::writeSector(sector, src);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool DedicatedSpiCard::writeSectors(
|
||||
uint32_t sector, const uint8_t* src, size_t ns) {
|
||||
bool DedicatedSpiCard::writeSectors(uint32_t sector, const uint8_t* src,
|
||||
size_t ns) {
|
||||
if (sdState() != WRITE_STATE || m_curSector != sector) {
|
||||
if (!writeStart(sector)) {
|
||||
goto fail;
|
||||
|
||||
@@ -24,25 +24,43 @@
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* \brief SdSpiCard class for V2 SD/SDHC cards
|
||||
* \brief Classes for SPI access to SD/SDHC cards.
|
||||
*/
|
||||
#ifndef SdSpiCard_h
|
||||
#define SdSpiCard_h
|
||||
#include <stddef.h>
|
||||
|
||||
#include "../SpiDriver/SdSpiDriver.h"
|
||||
#include "../common/SysCall.h"
|
||||
#include "SdCardInfo.h"
|
||||
#include "SdCardInterface.h"
|
||||
#include "../SpiDriver/SdSpiDriver.h"
|
||||
/** Verify correct SPI active if non-zero. */
|
||||
#define CHECK_SPI_ACTIVE 0
|
||||
#if CHECK_SPI_ACTIVE
|
||||
/** Check SPI active. */
|
||||
#define SPI_ASSERT_ACTIVE {if (!m_spiActive) {\
|
||||
Serial.print(F("SPI_ASSERTACTIVE"));\
|
||||
Serial.println(__LINE__);}}
|
||||
#define SPI_ASSERT_ACTIVE \
|
||||
{ \
|
||||
if (!m_spiActive) { \
|
||||
Serial.print(F("SPI_ASSERT_ACTIVE")); \
|
||||
Serial.println(__LINE__); \
|
||||
while (true) \
|
||||
; \
|
||||
} \
|
||||
}
|
||||
#define SPI_ASSERT_NOT_ACTIVE \
|
||||
{ \
|
||||
if (m_spiActive) { \
|
||||
Serial.print(F("SPI_ASSERT_NOT_ACTIVE")); \
|
||||
Serial.println(__LINE__); \
|
||||
while (true) \
|
||||
; \
|
||||
} \
|
||||
}
|
||||
#else // CHECK_SPI_ACTIVE
|
||||
/** Do not check SPI active. */
|
||||
/** Check for SPI active. */
|
||||
#define SPI_ASSERT_ACTIVE
|
||||
/** Check for SPI not active. */
|
||||
#define SPI_ASSERT_NOT_ACTIVE
|
||||
#endif // CHECK_SPI_ACTIVE
|
||||
//==============================================================================
|
||||
/**
|
||||
@@ -53,7 +71,7 @@
|
||||
class SharedSpiCard : public SdCardInterface {
|
||||
#elif USE_BLOCK_DEVICE_INTERFACE
|
||||
class SharedSpiCard : public FsBlockDeviceInterface {
|
||||
#else // HAS_SDIO_CLASS
|
||||
#else // HAS_SDIO_CLASS
|
||||
class SharedSpiCard {
|
||||
#endif // HAS_SDIO_CLASS
|
||||
public:
|
||||
@@ -64,7 +82,7 @@ class SharedSpiCard {
|
||||
/** SD is in multi-sector write state. */
|
||||
static const uint8_t WRITE_STATE = 2;
|
||||
/** Construct an instance of SharedSpiCard. */
|
||||
SharedSpiCard() {}
|
||||
SharedSpiCard() { initSharedSpiCard(); }
|
||||
/** Initialize the SD card.
|
||||
* \param[in] spiConfig SPI card configuration.
|
||||
* \return true for success or false for failure.
|
||||
@@ -103,21 +121,18 @@ class SharedSpiCard {
|
||||
* \param[in] code value for error code.
|
||||
*/
|
||||
void error(uint8_t code) {
|
||||
// (void)code;
|
||||
// (void)code;
|
||||
m_errorCode = code;
|
||||
}
|
||||
/**
|
||||
* \return code for the last error. See SdCardInfo.h for a list of error codes.
|
||||
* \return code for the last error. See SdCardInfo.h for a list of error
|
||||
* codes.
|
||||
*/
|
||||
uint8_t errorCode() const {
|
||||
return m_errorCode;
|
||||
}
|
||||
uint8_t errorCode() const { return m_errorCode; }
|
||||
/** \return error data for last error. */
|
||||
uint32_t errorData() const {
|
||||
return m_status;
|
||||
}
|
||||
uint32_t errorData() const { return m_status; }
|
||||
/** \return false for shared class. */
|
||||
bool hasDedicatedSpi() {return false;}
|
||||
bool hasDedicatedSpi() { return false; }
|
||||
/**
|
||||
* Check for busy. MISO low indicates the card is busy.
|
||||
*
|
||||
@@ -125,7 +140,7 @@ class SharedSpiCard {
|
||||
*/
|
||||
bool isBusy();
|
||||
/** \return false, can't be in dedicated state. */
|
||||
bool isDedicatedSpi() {return false;}
|
||||
bool isDedicatedSpi() { return false; }
|
||||
/**
|
||||
* Read a card's CID register. The CID contains card identification
|
||||
* information such as Manufacturer ID, Product name, Product serial
|
||||
@@ -135,9 +150,7 @@ class SharedSpiCard {
|
||||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool readCID(cid_t* cid) {
|
||||
return readRegister(CMD10, cid);
|
||||
}
|
||||
bool readCID(cid_t* cid) { return readRegister(CMD10, cid); }
|
||||
/**
|
||||
* Read a card's CSD register. The CSD contains Card-Specific Data that
|
||||
* provides information regarding access to the card's contents.
|
||||
@@ -146,9 +159,7 @@ class SharedSpiCard {
|
||||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool readCSD(csd_t* csd) {
|
||||
return readRegister(CMD9, csd);
|
||||
}
|
||||
bool readCSD(csd_t* csd) { return readRegister(CMD9, csd); }
|
||||
/** Read one data sector in a multiple sector read sequence
|
||||
*
|
||||
* \param[out] dst Pointer to the location for the data to be read.
|
||||
@@ -196,18 +207,18 @@ class SharedSpiCard {
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool readStart(uint32_t sector);
|
||||
/** Return the 64 byte card status
|
||||
/** Return the 64 byte SD Status register.
|
||||
* \param[out] status location for 64 status bytes.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool readStatus(SdStatus* status);
|
||||
bool readSDS(sds_t* status);
|
||||
/** End a read multiple sectors sequence.
|
||||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool readStop();
|
||||
/** \return SD multi-sector read/write state */
|
||||
uint8_t sdState() {return m_state;}
|
||||
uint8_t sdState() { return m_state; }
|
||||
/**
|
||||
* Determine the size of an SD flash memory card.
|
||||
*
|
||||
@@ -237,9 +248,7 @@ class SharedSpiCard {
|
||||
/** Return the card type: SD V1, SD V2 or SDHC/SDXC
|
||||
* \return 0 - SD V1, 1 - SD V2, or 3 - SDHC/SDXC.
|
||||
*/
|
||||
uint8_t type() const {
|
||||
return m_type;
|
||||
}
|
||||
uint8_t type() const { return m_type; }
|
||||
/**
|
||||
* Write a 512 byte sector to an SD card.
|
||||
*
|
||||
@@ -288,32 +297,18 @@ class SharedSpiCard {
|
||||
uint8_t cardCommand(uint8_t cmd, uint32_t arg);
|
||||
bool readData(uint8_t* dst, size_t count);
|
||||
bool readRegister(uint8_t cmd, void* buf);
|
||||
void spiSelect() {
|
||||
sdCsWrite(m_csPin, false);
|
||||
}
|
||||
void spiSelect() { sdCsWrite(m_csPin, false); }
|
||||
void spiStart();
|
||||
void spiStop();
|
||||
void spiUnselect() {
|
||||
sdCsWrite(m_csPin, true);
|
||||
}
|
||||
void type(uint8_t value) {
|
||||
m_type = value;
|
||||
}
|
||||
void spiUnselect() { sdCsWrite(m_csPin, true); }
|
||||
void type(uint8_t value) { m_type = value; }
|
||||
bool waitReady(uint16_t ms);
|
||||
bool writeData(uint8_t token, const uint8_t* src);
|
||||
#if SPI_DRIVER_SELECT < 2
|
||||
void spiActivate() {
|
||||
m_spiDriver.activate();
|
||||
}
|
||||
void spiBegin(SdSpiConfig spiConfig) {
|
||||
m_spiDriver.begin(spiConfig);
|
||||
}
|
||||
void spiDeactivate() {
|
||||
m_spiDriver.deactivate();
|
||||
}
|
||||
void spiEnd() {
|
||||
m_spiDriver.end();
|
||||
}
|
||||
void spiActivate() { m_spiDriver.activate(); }
|
||||
void spiBegin(SdSpiConfig spiConfig) { m_spiDriver.begin(spiConfig); }
|
||||
void spiDeactivate() { m_spiDriver.deactivate(); }
|
||||
void spiEnd() { m_spiDriver.end(); }
|
||||
uint8_t spiReceive() {
|
||||
SPI_ASSERT_ACTIVE;
|
||||
return m_spiDriver.receive();
|
||||
@@ -330,23 +325,13 @@ class SharedSpiCard {
|
||||
SPI_ASSERT_ACTIVE;
|
||||
m_spiDriver.send(buf, n);
|
||||
}
|
||||
void spiSetSckSpeed(uint32_t maxSck) {
|
||||
m_spiDriver.setSckSpeed(maxSck);
|
||||
}
|
||||
void spiSetSckSpeed(uint32_t maxSck) { m_spiDriver.setSckSpeed(maxSck); }
|
||||
SdSpiDriver m_spiDriver;
|
||||
#else // SPI_DRIVER_SELECT < 2
|
||||
void spiActivate() {
|
||||
m_spiDriverPtr->activate();
|
||||
}
|
||||
void spiBegin(SdSpiConfig spiConfig) {
|
||||
m_spiDriverPtr->begin(spiConfig);
|
||||
}
|
||||
void spiDeactivate() {
|
||||
m_spiDriverPtr->deactivate();
|
||||
}
|
||||
void spiEnd() {
|
||||
m_spiDriverPtr->end();
|
||||
}
|
||||
void spiActivate() { m_spiDriverPtr->activate(); }
|
||||
void spiBegin(SdSpiConfig spiConfig) { m_spiDriverPtr->begin(spiConfig); }
|
||||
void spiDeactivate() { m_spiDriverPtr->deactivate(); }
|
||||
void spiEnd() { m_spiDriverPtr->end(); }
|
||||
uint8_t spiReceive() {
|
||||
SPI_ASSERT_ACTIVE;
|
||||
return m_spiDriverPtr->receive();
|
||||
@@ -363,21 +348,27 @@ class SharedSpiCard {
|
||||
SPI_ASSERT_ACTIVE;
|
||||
m_spiDriverPtr->send(buf, n);
|
||||
}
|
||||
void spiSetSckSpeed(uint32_t maxSck) {
|
||||
m_spiDriverPtr->setSckSpeed(maxSck);
|
||||
}
|
||||
void spiSetSckSpeed(uint32_t maxSck) { m_spiDriverPtr->setSckSpeed(maxSck); }
|
||||
SdSpiDriver* m_spiDriverPtr;
|
||||
|
||||
#endif // SPI_DRIVER_SELECT < 2
|
||||
bool m_beginCalled = false;
|
||||
void initSharedSpiCard() {
|
||||
m_beginCalled = false;
|
||||
m_csPin = 0;
|
||||
m_errorCode = SD_CARD_ERROR_INIT_NOT_CALLED;
|
||||
m_spiActive = false;
|
||||
m_state = IDLE_STATE;
|
||||
m_status = 0;
|
||||
m_type = 0;
|
||||
}
|
||||
bool m_beginCalled;
|
||||
SdCsPin_t m_csPin;
|
||||
uint8_t m_errorCode = SD_CARD_ERROR_INIT_NOT_CALLED;
|
||||
bool m_spiActive;
|
||||
uint8_t m_errorCode;
|
||||
bool m_spiActive;
|
||||
uint8_t m_state;
|
||||
uint8_t m_status;
|
||||
uint8_t m_type = 0;
|
||||
uint8_t m_type;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class DedicatedSpiCard
|
||||
@@ -386,16 +377,16 @@ class SharedSpiCard {
|
||||
class DedicatedSpiCard : public SharedSpiCard {
|
||||
public:
|
||||
/** Construct an instance of DedicatedSpiCard. */
|
||||
DedicatedSpiCard() {}
|
||||
DedicatedSpiCard() = default;
|
||||
/** Initialize the SD card.
|
||||
* \param[in] spiConfig SPI card configuration.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool begin(SdSpiConfig spiConfig);
|
||||
/** \return true, can be in dedicaded state. */
|
||||
bool hasDedicatedSpi() {return true;}
|
||||
bool hasDedicatedSpi() { return true; }
|
||||
/** \return true if in dedicated SPI state. */
|
||||
bool isDedicatedSpi() {return m_dedicatedSpi;}
|
||||
bool isDedicatedSpi() { return m_dedicatedSpi; }
|
||||
/**
|
||||
* Read a 512 byte sector from an SD card.
|
||||
*
|
||||
@@ -437,7 +428,7 @@ class DedicatedSpiCard : public SharedSpiCard {
|
||||
bool writeSectors(uint32_t sector, const uint8_t* src, size_t ns);
|
||||
|
||||
private:
|
||||
uint32_t m_curSector;
|
||||
uint32_t m_curSector = 0;
|
||||
bool m_dedicatedSpi = false;
|
||||
};
|
||||
//==============================================================================
|
||||
|
||||
@@ -22,12 +22,17 @@
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* \brief Classes for SDIO cards.
|
||||
*/
|
||||
#ifndef SdioCard_h
|
||||
#define SdioCard_h
|
||||
#include "../common/SysCall.h"
|
||||
#include "SdCardInterface.h"
|
||||
|
||||
/** Use programmed I/O with FIFO. */
|
||||
#define FIFO_SDIO 0
|
||||
/** Use programmed I/O with DMA. */
|
||||
#define DMA_SDIO 1
|
||||
/**
|
||||
* \class SdioConfig
|
||||
@@ -42,9 +47,10 @@ class SdioConfig {
|
||||
*/
|
||||
explicit SdioConfig(uint8_t opt) : m_options(opt) {}
|
||||
/** \return SDIO card options. */
|
||||
uint8_t options() {return m_options;}
|
||||
uint8_t options() { return m_options; }
|
||||
/** \return true if DMA_SDIO. */
|
||||
bool useDma() {return m_options & DMA_SDIO;}
|
||||
bool useDma() { return m_options & DMA_SDIO; }
|
||||
|
||||
private:
|
||||
uint8_t m_options = FIFO_SDIO;
|
||||
};
|
||||
@@ -73,7 +79,7 @@ class SdioCard : public SdCardInterface {
|
||||
void end() {}
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
uint32_t __attribute__((error("use sectorCount()"))) cardSize();
|
||||
uint32_t __attribute__((error("use sectorCount()"))) cardSize();
|
||||
#endif // DOXYGEN_SHOULD_SKIP_THIS
|
||||
/** Erase a range of sectors.
|
||||
*
|
||||
@@ -89,7 +95,8 @@ class SdioCard : public SdCardInterface {
|
||||
*/
|
||||
bool erase(uint32_t firstSector, uint32_t lastSector);
|
||||
/**
|
||||
* \return code for the last error. See SdCardInfo.h for a list of error codes.
|
||||
* \return code for the last error. See SdCardInfo.h for a list of error
|
||||
* codes.
|
||||
*/
|
||||
uint8_t errorCode() const;
|
||||
/** \return error data for last error. */
|
||||
@@ -158,7 +165,12 @@ class SdioCard : public SdCardInterface {
|
||||
* \param[out] scr Value of SCR register.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool readSCR(scr_t *scr);
|
||||
bool readSCR(scr_t* scr);
|
||||
/** Return the 64 byte SD Status register.
|
||||
* \param[out] sds location for 64 status bytes.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool readSDS(sds_t* sds);
|
||||
/** Start a read multiple sectors sequence.
|
||||
*
|
||||
* \param[in] sector Address of first sector in sequence.
|
||||
@@ -186,7 +198,7 @@ class SdioCard : public SdCardInterface {
|
||||
bool readStop();
|
||||
/** \return SDIO card status. */
|
||||
uint32_t status();
|
||||
/**
|
||||
/**
|
||||
* Determine the size of an SD flash memory card.
|
||||
*
|
||||
* \return The number of 512 byte data sectors in the card
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
*/
|
||||
#if defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(__IMXRT1062__)
|
||||
#include "SdioTeensy.h"
|
||||
|
||||
#include "SdCardInfo.h"
|
||||
#include "SdioCard.h"
|
||||
//==============================================================================
|
||||
@@ -36,39 +37,34 @@ const uint32_t CMD8_RETRIES = 3;
|
||||
const uint32_t BUSY_TIMEOUT_MICROS = 1000000;
|
||||
//==============================================================================
|
||||
const uint32_t SDHC_IRQSTATEN_MASK =
|
||||
SDHC_IRQSTATEN_DMAESEN | SDHC_IRQSTATEN_AC12ESEN |
|
||||
SDHC_IRQSTATEN_DEBESEN | SDHC_IRQSTATEN_DCESEN |
|
||||
SDHC_IRQSTATEN_DTOESEN | SDHC_IRQSTATEN_CIESEN |
|
||||
SDHC_IRQSTATEN_CEBESEN | SDHC_IRQSTATEN_CCESEN |
|
||||
SDHC_IRQSTATEN_CTOESEN | SDHC_IRQSTATEN_DINTSEN |
|
||||
SDHC_IRQSTATEN_TCSEN | SDHC_IRQSTATEN_CCSEN;
|
||||
SDHC_IRQSTATEN_DMAESEN | SDHC_IRQSTATEN_AC12ESEN | SDHC_IRQSTATEN_DEBESEN |
|
||||
SDHC_IRQSTATEN_DCESEN | SDHC_IRQSTATEN_DTOESEN | SDHC_IRQSTATEN_CIESEN |
|
||||
SDHC_IRQSTATEN_CEBESEN | SDHC_IRQSTATEN_CCESEN | SDHC_IRQSTATEN_CTOESEN |
|
||||
SDHC_IRQSTATEN_DINTSEN | SDHC_IRQSTATEN_TCSEN | SDHC_IRQSTATEN_CCSEN;
|
||||
|
||||
const uint32_t SDHC_IRQSTAT_CMD_ERROR =
|
||||
SDHC_IRQSTAT_CIE | SDHC_IRQSTAT_CEBE |
|
||||
SDHC_IRQSTAT_CCE | SDHC_IRQSTAT_CTOE;
|
||||
SDHC_IRQSTAT_CIE | SDHC_IRQSTAT_CEBE | SDHC_IRQSTAT_CCE | SDHC_IRQSTAT_CTOE;
|
||||
|
||||
const uint32_t SDHC_IRQSTAT_DATA_ERROR =
|
||||
SDHC_IRQSTAT_AC12E | SDHC_IRQSTAT_DEBE |
|
||||
SDHC_IRQSTAT_DCE | SDHC_IRQSTAT_DTOE;
|
||||
const uint32_t SDHC_IRQSTAT_DATA_ERROR = SDHC_IRQSTAT_AC12E |
|
||||
SDHC_IRQSTAT_DEBE | SDHC_IRQSTAT_DCE |
|
||||
SDHC_IRQSTAT_DTOE;
|
||||
|
||||
const uint32_t SDHC_IRQSTAT_ERROR =
|
||||
SDHC_IRQSTAT_DMAE | SDHC_IRQSTAT_CMD_ERROR |
|
||||
SDHC_IRQSTAT_DATA_ERROR;
|
||||
SDHC_IRQSTAT_DMAE | SDHC_IRQSTAT_CMD_ERROR | SDHC_IRQSTAT_DATA_ERROR;
|
||||
|
||||
const uint32_t SDHC_IRQSIGEN_MASK =
|
||||
SDHC_IRQSIGEN_DMAEIEN | SDHC_IRQSIGEN_AC12EIEN |
|
||||
SDHC_IRQSIGEN_DEBEIEN | SDHC_IRQSIGEN_DCEIEN |
|
||||
SDHC_IRQSIGEN_DTOEIEN | SDHC_IRQSIGEN_CIEIEN |
|
||||
SDHC_IRQSIGEN_CEBEIEN | SDHC_IRQSIGEN_CCEIEN |
|
||||
SDHC_IRQSIGEN_CTOEIEN | SDHC_IRQSIGEN_TCIEN;
|
||||
SDHC_IRQSIGEN_DMAEIEN | SDHC_IRQSIGEN_AC12EIEN | SDHC_IRQSIGEN_DEBEIEN |
|
||||
SDHC_IRQSIGEN_DCEIEN | SDHC_IRQSIGEN_DTOEIEN | SDHC_IRQSIGEN_CIEIEN |
|
||||
SDHC_IRQSIGEN_CEBEIEN | SDHC_IRQSIGEN_CCEIEN | SDHC_IRQSIGEN_CTOEIEN |
|
||||
SDHC_IRQSIGEN_TCIEN;
|
||||
//==============================================================================
|
||||
const uint32_t CMD_RESP_NONE = SDHC_XFERTYP_RSPTYP(0);
|
||||
|
||||
const uint32_t CMD_RESP_R1 = SDHC_XFERTYP_CICEN | SDHC_XFERTYP_CCCEN |
|
||||
SDHC_XFERTYP_RSPTYP(2);
|
||||
const uint32_t CMD_RESP_R1 =
|
||||
SDHC_XFERTYP_CICEN | SDHC_XFERTYP_CCCEN | SDHC_XFERTYP_RSPTYP(2);
|
||||
|
||||
const uint32_t CMD_RESP_R1b = SDHC_XFERTYP_CICEN | SDHC_XFERTYP_CCCEN |
|
||||
SDHC_XFERTYP_RSPTYP(3);
|
||||
const uint32_t CMD_RESP_R1b =
|
||||
SDHC_XFERTYP_CICEN | SDHC_XFERTYP_CCCEN | SDHC_XFERTYP_RSPTYP(3);
|
||||
|
||||
const uint32_t CMD_RESP_R2 = SDHC_XFERTYP_CCCEN | SDHC_XFERTYP_RSPTYP(1);
|
||||
|
||||
@@ -86,26 +82,23 @@ const uint32_t DATA_READ_DMA = DATA_READ | SDHC_XFERTYP_DMAEN;
|
||||
const uint32_t DATA_READ_MULTI_DMA = DATA_READ_DMA | SDHC_XFERTYP_MSBSEL |
|
||||
SDHC_XFERTYP_AC12EN | SDHC_XFERTYP_BCEN;
|
||||
|
||||
const uint32_t DATA_READ_MULTI_PGM = DATA_READ | SDHC_XFERTYP_MSBSEL |
|
||||
SDHC_XFERTYP_BCEN;
|
||||
const uint32_t DATA_READ_MULTI_PGM =
|
||||
DATA_READ | SDHC_XFERTYP_MSBSEL | SDHC_XFERTYP_BCEN;
|
||||
|
||||
const uint32_t DATA_WRITE_DMA = SDHC_XFERTYP_DPSEL | SDHC_XFERTYP_DMAEN;
|
||||
|
||||
const uint32_t DATA_WRITE_MULTI_DMA = DATA_WRITE_DMA | SDHC_XFERTYP_MSBSEL |
|
||||
SDHC_XFERTYP_AC12EN | SDHC_XFERTYP_BCEN;
|
||||
|
||||
const uint32_t DATA_WRITE_MULTI_PGM = SDHC_XFERTYP_DPSEL | SDHC_XFERTYP_MSBSEL |
|
||||
SDHC_XFERTYP_BCEN;
|
||||
const uint32_t DATA_WRITE_MULTI_PGM =
|
||||
SDHC_XFERTYP_DPSEL | SDHC_XFERTYP_MSBSEL | SDHC_XFERTYP_BCEN;
|
||||
|
||||
#elif defined(__IMXRT1062__)
|
||||
// Use low bits for SDHC_MIX_CTRL since bits 15-0 of SDHC_XFERTYP are reserved.
|
||||
const uint32_t SDHC_MIX_CTRL_MASK = SDHC_MIX_CTRL_DMAEN | SDHC_MIX_CTRL_BCEN |
|
||||
SDHC_MIX_CTRL_AC12EN |
|
||||
SDHC_MIX_CTRL_DDR_EN |
|
||||
SDHC_MIX_CTRL_DTDSEL |
|
||||
SDHC_MIX_CTRL_MSBSEL |
|
||||
SDHC_MIX_CTRL_NIBBLE_POS |
|
||||
SDHC_MIX_CTRL_AC23EN;
|
||||
const uint32_t SDHC_MIX_CTRL_MASK =
|
||||
SDHC_MIX_CTRL_DMAEN | SDHC_MIX_CTRL_BCEN | SDHC_MIX_CTRL_AC12EN |
|
||||
SDHC_MIX_CTRL_DDR_EN | SDHC_MIX_CTRL_DTDSEL | SDHC_MIX_CTRL_MSBSEL |
|
||||
SDHC_MIX_CTRL_NIBBLE_POS | SDHC_MIX_CTRL_AC23EN;
|
||||
|
||||
const uint32_t DATA_READ = SDHC_MIX_CTRL_DTDSEL | SDHC_XFERTYP_DPSEL;
|
||||
|
||||
@@ -116,7 +109,6 @@ const uint32_t DATA_READ_MULTI_DMA = DATA_READ_DMA | SDHC_MIX_CTRL_MSBSEL |
|
||||
|
||||
const uint32_t DATA_READ_MULTI_PGM = DATA_READ | SDHC_MIX_CTRL_MSBSEL;
|
||||
|
||||
|
||||
const uint32_t DATA_WRITE_DMA = SDHC_XFERTYP_DPSEL | SDHC_MIX_CTRL_DMAEN;
|
||||
|
||||
const uint32_t DATA_WRITE_MULTI_DMA = DATA_WRITE_DMA | SDHC_MIX_CTRL_MSBSEL |
|
||||
@@ -128,10 +120,13 @@ const uint32_t DATA_WRITE_MULTI_PGM = SDHC_XFERTYP_DPSEL | SDHC_MIX_CTRL_MSBSEL;
|
||||
|
||||
const uint32_t ACMD6_XFERTYP = SDHC_XFERTYP_CMDINX(ACMD6) | CMD_RESP_R1;
|
||||
|
||||
const uint32_t ACMD13_XFERTYP =
|
||||
SDHC_XFERTYP_CMDINX(ACMD13) | CMD_RESP_R1 | DATA_READ_DMA;
|
||||
|
||||
const uint32_t ACMD41_XFERTYP = SDHC_XFERTYP_CMDINX(ACMD41) | CMD_RESP_R3;
|
||||
|
||||
const uint32_t ACMD51_XFERTYP = SDHC_XFERTYP_CMDINX(ACMD51) | CMD_RESP_R1 |
|
||||
DATA_READ_DMA;
|
||||
const uint32_t ACMD51_XFERTYP =
|
||||
SDHC_XFERTYP_CMDINX(ACMD51) | CMD_RESP_R1 | DATA_READ_DMA;
|
||||
|
||||
const uint32_t CMD0_XFERTYP = SDHC_XFERTYP_CMDINX(CMD0) | CMD_RESP_NONE;
|
||||
|
||||
@@ -139,8 +134,8 @@ const uint32_t CMD2_XFERTYP = SDHC_XFERTYP_CMDINX(CMD2) | CMD_RESP_R2;
|
||||
|
||||
const uint32_t CMD3_XFERTYP = SDHC_XFERTYP_CMDINX(CMD3) | CMD_RESP_R6;
|
||||
|
||||
const uint32_t CMD6_XFERTYP = SDHC_XFERTYP_CMDINX(CMD6) | CMD_RESP_R1 |
|
||||
DATA_READ_DMA;
|
||||
const uint32_t CMD6_XFERTYP =
|
||||
SDHC_XFERTYP_CMDINX(CMD6) | CMD_RESP_R1 | DATA_READ_DMA;
|
||||
|
||||
const uint32_t CMD7_XFERTYP = SDHC_XFERTYP_CMDINX(CMD7) | CMD_RESP_R1b;
|
||||
|
||||
@@ -152,28 +147,28 @@ const uint32_t CMD10_XFERTYP = SDHC_XFERTYP_CMDINX(CMD10) | CMD_RESP_R2;
|
||||
|
||||
const uint32_t CMD11_XFERTYP = SDHC_XFERTYP_CMDINX(CMD11) | CMD_RESP_R1;
|
||||
|
||||
const uint32_t CMD12_XFERTYP = SDHC_XFERTYP_CMDINX(CMD12) | CMD_RESP_R1b |
|
||||
SDHC_XFERTYP_CMDTYP(3);
|
||||
const uint32_t CMD12_XFERTYP =
|
||||
SDHC_XFERTYP_CMDINX(CMD12) | CMD_RESP_R1b | SDHC_XFERTYP_CMDTYP(3);
|
||||
|
||||
const uint32_t CMD13_XFERTYP = SDHC_XFERTYP_CMDINX(CMD13) | CMD_RESP_R1;
|
||||
|
||||
const uint32_t CMD17_DMA_XFERTYP = SDHC_XFERTYP_CMDINX(CMD17) | CMD_RESP_R1 |
|
||||
DATA_READ_DMA;
|
||||
const uint32_t CMD17_DMA_XFERTYP =
|
||||
SDHC_XFERTYP_CMDINX(CMD17) | CMD_RESP_R1 | DATA_READ_DMA;
|
||||
|
||||
const uint32_t CMD18_DMA_XFERTYP = SDHC_XFERTYP_CMDINX(CMD18) | CMD_RESP_R1 |
|
||||
DATA_READ_MULTI_DMA;
|
||||
const uint32_t CMD18_DMA_XFERTYP =
|
||||
SDHC_XFERTYP_CMDINX(CMD18) | CMD_RESP_R1 | DATA_READ_MULTI_DMA;
|
||||
|
||||
const uint32_t CMD18_PGM_XFERTYP = SDHC_XFERTYP_CMDINX(CMD18) | CMD_RESP_R1 |
|
||||
DATA_READ_MULTI_PGM;
|
||||
const uint32_t CMD18_PGM_XFERTYP =
|
||||
SDHC_XFERTYP_CMDINX(CMD18) | CMD_RESP_R1 | DATA_READ_MULTI_PGM;
|
||||
|
||||
const uint32_t CMD24_DMA_XFERTYP = SDHC_XFERTYP_CMDINX(CMD24) | CMD_RESP_R1 |
|
||||
DATA_WRITE_DMA;
|
||||
const uint32_t CMD24_DMA_XFERTYP =
|
||||
SDHC_XFERTYP_CMDINX(CMD24) | CMD_RESP_R1 | DATA_WRITE_DMA;
|
||||
|
||||
const uint32_t CMD25_DMA_XFERTYP = SDHC_XFERTYP_CMDINX(CMD25) | CMD_RESP_R1 |
|
||||
DATA_WRITE_MULTI_DMA;
|
||||
const uint32_t CMD25_DMA_XFERTYP =
|
||||
SDHC_XFERTYP_CMDINX(CMD25) | CMD_RESP_R1 | DATA_WRITE_MULTI_DMA;
|
||||
|
||||
const uint32_t CMD25_PGM_XFERTYP = SDHC_XFERTYP_CMDINX(CMD25) | CMD_RESP_R1 |
|
||||
DATA_WRITE_MULTI_PGM;
|
||||
const uint32_t CMD25_PGM_XFERTYP =
|
||||
SDHC_XFERTYP_CMDINX(CMD25) | CMD_RESP_R1 | DATA_WRITE_MULTI_PGM;
|
||||
|
||||
const uint32_t CMD32_XFERTYP = SDHC_XFERTYP_CMDINX(CMD32) | CMD_RESP_R1;
|
||||
|
||||
@@ -212,12 +207,20 @@ static uint32_t m_ocr;
|
||||
static cid_t m_cid;
|
||||
static csd_t m_csd;
|
||||
static scr_t m_scr;
|
||||
static sds_t m_sds;
|
||||
//==============================================================================
|
||||
#define DBG_TRACE Serial.print("TRACE."); Serial.println(__LINE__); delay(200);
|
||||
#define DBG_TRACE \
|
||||
Serial.print("TRACE."); \
|
||||
Serial.println(__LINE__); \
|
||||
delay(200);
|
||||
#define USE_DEBUG_MODE 0
|
||||
#if USE_DEBUG_MODE
|
||||
#define DBG_IRQSTAT() if (SDHC_IRQSTAT) {Serial.print(__LINE__);\
|
||||
Serial.print(" IRQSTAT "); Serial.println(SDHC_IRQSTAT, HEX);}
|
||||
#define DBG_IRQSTAT() \
|
||||
if (SDHC_IRQSTAT) { \
|
||||
Serial.print(__LINE__); \
|
||||
Serial.print(" IRQSTAT "); \
|
||||
Serial.println(SDHC_IRQSTAT, HEX); \
|
||||
}
|
||||
static void printRegs(uint32_t line) {
|
||||
uint32_t blkattr = SDHC_BLKATTR;
|
||||
uint32_t xfertyp = SDHC_XFERTYP;
|
||||
@@ -234,36 +237,68 @@ static void printRegs(uint32_t line) {
|
||||
Serial.print(xfertyp >> 24);
|
||||
Serial.print(" TYP");
|
||||
Serial.print((xfertyp >> 2) & 3);
|
||||
if (xfertyp & SDHC_XFERTYP_DPSEL) {Serial.print(" DPSEL");}
|
||||
if (xfertyp & SDHC_XFERTYP_DPSEL) {
|
||||
Serial.print(" DPSEL");
|
||||
}
|
||||
Serial.println();
|
||||
Serial.print("PRSSTAT ");
|
||||
Serial.print(prsstat, HEX);
|
||||
if (prsstat & SDHC_PRSSTAT_BREN) {Serial.print(" BREN");}
|
||||
if (prsstat & SDHC_PRSSTAT_BWEN) {Serial.print(" BWEN");}
|
||||
if (prsstat & SDHC_PRSSTAT_RTA) {Serial.print(" RTA");}
|
||||
if (prsstat & SDHC_PRSSTAT_WTA) {Serial.print(" WTA");}
|
||||
if (prsstat & SDHC_PRSSTAT_SDOFF) {Serial.print(" SDOFF");}
|
||||
if (prsstat & SDHC_PRSSTAT_PEROFF) {Serial.print(" PEROFF");}
|
||||
if (prsstat & SDHC_PRSSTAT_HCKOFF) {Serial.print(" HCKOFF");}
|
||||
if (prsstat & SDHC_PRSSTAT_IPGOFF) {Serial.print(" IPGOFF");}
|
||||
if (prsstat & SDHC_PRSSTAT_SDSTB) {Serial.print(" SDSTB");}
|
||||
if (prsstat & SDHC_PRSSTAT_DLA) {Serial.print(" DLA");}
|
||||
if (prsstat & SDHC_PRSSTAT_CDIHB) {Serial.print(" CDIHB");}
|
||||
if (prsstat & SDHC_PRSSTAT_CIHB) {Serial.print(" CIHB");}
|
||||
if (prsstat & SDHC_PRSSTAT_BREN) {
|
||||
Serial.print(" BREN");
|
||||
}
|
||||
if (prsstat & SDHC_PRSSTAT_BWEN) {
|
||||
Serial.print(" BWEN");
|
||||
}
|
||||
if (prsstat & SDHC_PRSSTAT_RTA) {
|
||||
Serial.print(" RTA");
|
||||
}
|
||||
if (prsstat & SDHC_PRSSTAT_WTA) {
|
||||
Serial.print(" WTA");
|
||||
}
|
||||
if (prsstat & SDHC_PRSSTAT_SDOFF) {
|
||||
Serial.print(" SDOFF");
|
||||
}
|
||||
if (prsstat & SDHC_PRSSTAT_PEROFF) {
|
||||
Serial.print(" PEROFF");
|
||||
}
|
||||
if (prsstat & SDHC_PRSSTAT_HCKOFF) {
|
||||
Serial.print(" HCKOFF");
|
||||
}
|
||||
if (prsstat & SDHC_PRSSTAT_IPGOFF) {
|
||||
Serial.print(" IPGOFF");
|
||||
}
|
||||
if (prsstat & SDHC_PRSSTAT_SDSTB) {
|
||||
Serial.print(" SDSTB");
|
||||
}
|
||||
if (prsstat & SDHC_PRSSTAT_DLA) {
|
||||
Serial.print(" DLA");
|
||||
}
|
||||
if (prsstat & SDHC_PRSSTAT_CDIHB) {
|
||||
Serial.print(" CDIHB");
|
||||
}
|
||||
if (prsstat & SDHC_PRSSTAT_CIHB) {
|
||||
Serial.print(" CIHB");
|
||||
}
|
||||
Serial.println();
|
||||
Serial.print("PROCTL ");
|
||||
Serial.print(proctl, HEX);
|
||||
if (proctl & SDHC_PROCTL_SABGREQ) Serial.print(" SABGREQ");
|
||||
Serial.print(" EMODE");
|
||||
Serial.print((proctl >>4) & 3);
|
||||
Serial.print((proctl >> 4) & 3);
|
||||
Serial.print(" DWT");
|
||||
Serial.print((proctl >>1) & 3);
|
||||
Serial.print((proctl >> 1) & 3);
|
||||
Serial.println();
|
||||
Serial.print("IRQSTAT ");
|
||||
Serial.print(irqstat, HEX);
|
||||
if (irqstat & SDHC_IRQSTAT_BGE) {Serial.print(" BGE");}
|
||||
if (irqstat & SDHC_IRQSTAT_TC) {Serial.print(" TC");}
|
||||
if (irqstat & SDHC_IRQSTAT_CC) {Serial.print(" CC");}
|
||||
if (irqstat & SDHC_IRQSTAT_BGE) {
|
||||
Serial.print(" BGE");
|
||||
}
|
||||
if (irqstat & SDHC_IRQSTAT_TC) {
|
||||
Serial.print(" TC");
|
||||
}
|
||||
if (irqstat & SDHC_IRQSTAT_CC) {
|
||||
Serial.print(" CC");
|
||||
}
|
||||
Serial.print("\nm_irqstat ");
|
||||
Serial.println(m_irqstat, HEX);
|
||||
}
|
||||
@@ -298,12 +333,12 @@ static void sdIrs() {
|
||||
//------------------------------------------------------------------------------
|
||||
static void enableGPIO(bool enable) {
|
||||
const uint32_t PORT_CLK = PORT_PCR_MUX(4) | PORT_PCR_DSE;
|
||||
const uint32_t PORT_CMD_DATA = PORT_CLK | PORT_PCR_PE | PORT_PCR_PS;
|
||||
const uint32_t PORT_CMD_DATA = PORT_CLK | PORT_PCR_PE | PORT_PCR_PS;
|
||||
const uint32_t PORT_PUP = PORT_PCR_MUX(1) | PORT_PCR_PE | PORT_PCR_PS;
|
||||
|
||||
PORTE_PCR0 = enable ? PORT_CMD_DATA : PORT_PUP; // SDHC_D1
|
||||
PORTE_PCR1 = enable ? PORT_CMD_DATA : PORT_PUP; // SDHC_D0
|
||||
PORTE_PCR2 = enable ? PORT_CLK : PORT_PUP; // SDHC_CLK
|
||||
PORTE_PCR2 = enable ? PORT_CLK : PORT_PUP; // SDHC_CLK
|
||||
PORTE_PCR3 = enable ? PORT_CMD_DATA : PORT_PUP; // SDHC_CMD
|
||||
PORTE_PCR4 = enable ? PORT_CMD_DATA : PORT_PUP; // SDHC_D3
|
||||
PORTE_PCR5 = enable ? PORT_CMD_DATA : PORT_PUP; // SDHC_D2
|
||||
@@ -317,7 +352,7 @@ static void initClock() {
|
||||
// Enable SDHC clock.
|
||||
SIM_SCGC3 |= SIM_SCGC3_SDHC;
|
||||
}
|
||||
static uint32_t baseClock() { return F_CPU;}
|
||||
static uint32_t baseClock() { return F_CPU; }
|
||||
|
||||
#elif defined(__IMXRT1062__)
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -335,13 +370,13 @@ static void enableGPIO(bool enable) {
|
||||
const uint32_t CLOCK_MASK = IOMUXC_SW_PAD_CTL_PAD_PKE |
|
||||
#if defined(ARDUINO_TEENSY41)
|
||||
IOMUXC_SW_PAD_CTL_PAD_DSE(7) |
|
||||
#else // defined(ARDUINO_TEENSY41)
|
||||
#else // defined(ARDUINO_TEENSY41)
|
||||
IOMUXC_SW_PAD_CTL_PAD_DSE(4) | ///// WHG
|
||||
#endif // defined(ARDUINO_TEENSY41)
|
||||
IOMUXC_SW_PAD_CTL_PAD_SPEED(2);
|
||||
|
||||
const uint32_t DATA_MASK = CLOCK_MASK | IOMUXC_SW_PAD_CTL_PAD_PUE |
|
||||
IOMUXC_SW_PAD_CTL_PAD_PUS(1);
|
||||
const uint32_t DATA_MASK =
|
||||
CLOCK_MASK | IOMUXC_SW_PAD_CTL_PAD_PUE | IOMUXC_SW_PAD_CTL_PAD_PUS(1);
|
||||
if (enable) {
|
||||
gpioMux(0);
|
||||
IOMUXC_SW_PAD_CTL_PAD_GPIO_SD_B0_04 = DATA_MASK; // DAT2
|
||||
@@ -365,20 +400,20 @@ static void initClock() {
|
||||
/* Enable USDHC clock. */
|
||||
CCM_CCGR6 |= CCM_CCGR6_USDHC1(CCM_CCGR_ON);
|
||||
CCM_CSCDR1 &= ~(CCM_CSCDR1_USDHC1_CLK_PODF_MASK);
|
||||
CCM_CSCMR1 |= CCM_CSCMR1_USDHC1_CLK_SEL; // PLL2PFD0
|
||||
// CCM_CSCDR1 |= CCM_CSCDR1_USDHC1_CLK_PODF((7)); / &0x7 WHG
|
||||
CCM_CSCMR1 |= CCM_CSCMR1_USDHC1_CLK_SEL; // PLL2PFD0
|
||||
// CCM_CSCDR1 |= CCM_CSCDR1_USDHC1_CLK_PODF((7)); / &0x7 WHG
|
||||
CCM_CSCDR1 |= CCM_CSCDR1_USDHC1_CLK_PODF((1));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
static uint32_t baseClock() {
|
||||
uint32_t divider = ((CCM_CSCDR1 >> 11) & 0x7) + 1;
|
||||
return (528000000U * 3)/((CCM_ANALOG_PFD_528 & 0x3F)/6)/divider;
|
||||
return (528000000U * 3) / ((CCM_ANALOG_PFD_528 & 0x3F) / 6) / divider;
|
||||
}
|
||||
#endif // defined(__MK64FX512__) || defined(__MK66FX1M0__)
|
||||
//==============================================================================
|
||||
// Static functions.
|
||||
static bool cardAcmd(uint32_t rca, uint32_t xfertyp, uint32_t arg) {
|
||||
return cardCommand(CMD55_XFERTYP, rca) && cardCommand (xfertyp, arg);
|
||||
return cardCommand(CMD55_XFERTYP, rca) && cardCommand(xfertyp, arg);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
static bool cardCommand(uint32_t xfertyp, uint32_t arg) {
|
||||
@@ -402,8 +437,25 @@ static bool cardCommand(uint32_t xfertyp, uint32_t arg) {
|
||||
m_irqstat = SDHC_IRQSTAT;
|
||||
SDHC_IRQSTAT = m_irqstat;
|
||||
|
||||
return (m_irqstat & SDHC_IRQSTAT_CC) &&
|
||||
!(m_irqstat & SDHC_IRQSTAT_CMD_ERROR);
|
||||
return (m_irqstat & SDHC_IRQSTAT_CC) && !(m_irqstat & SDHC_IRQSTAT_CMD_ERROR);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
static bool cardACMD13(sds_t* scr) {
|
||||
// ACMD13 returns 64 bytes.
|
||||
if (waitTimeout(isBusyCMD13)) {
|
||||
return sdError(SD_CARD_ERROR_CMD13);
|
||||
}
|
||||
enableDmaIrs();
|
||||
SDHC_DSADDR = (uint32_t)scr;
|
||||
SDHC_BLKATTR = SDHC_BLKATTR_BLKCNT(1) | SDHC_BLKATTR_BLKSIZE(64);
|
||||
SDHC_IRQSIGEN = SDHC_IRQSIGEN_MASK;
|
||||
if (!cardAcmd(m_rca, ACMD13_XFERTYP, 0)) {
|
||||
return sdError(SD_CARD_ERROR_ACMD13);
|
||||
}
|
||||
if (!waitDmaStatus()) {
|
||||
return sdError(SD_CARD_ERROR_DMA);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
static bool cardACMD51(scr_t* scr) {
|
||||
@@ -412,7 +464,7 @@ static bool cardACMD51(scr_t* scr) {
|
||||
return sdError(SD_CARD_ERROR_CMD13);
|
||||
}
|
||||
enableDmaIrs();
|
||||
SDHC_DSADDR = (uint32_t)scr;
|
||||
SDHC_DSADDR = (uint32_t)scr;
|
||||
SDHC_BLKATTR = SDHC_BLKATTR_BLKCNT(1) | SDHC_BLKATTR_BLKSIZE(8);
|
||||
SDHC_IRQSIGEN = SDHC_IRQSIGEN_MASK;
|
||||
if (!cardAcmd(m_rca, ACMD51_XFERTYP, 0)) {
|
||||
@@ -435,7 +487,7 @@ static void initSDHC() {
|
||||
// Disable GPIO clock.
|
||||
enableGPIO(false);
|
||||
|
||||
#if defined (__IMXRT1062__)
|
||||
#if defined(__IMXRT1062__)
|
||||
SDHC_MIX_CTRL |= 0x80000000;
|
||||
#endif // (__IMXRT1062__)
|
||||
|
||||
@@ -454,7 +506,7 @@ static void initSDHC() {
|
||||
SDHC_IRQSTATEN = SDHC_IRQSTATEN_MASK;
|
||||
|
||||
attachInterruptVector(IRQ_SDHC, sdIrs);
|
||||
NVIC_SET_PRIORITY(IRQ_SDHC, 6*16);
|
||||
NVIC_SET_PRIORITY(IRQ_SDHC, 6 * 16);
|
||||
NVIC_ENABLE_IRQ(IRQ_SDHC);
|
||||
|
||||
// Send 80 clocks to card.
|
||||
@@ -475,32 +527,22 @@ static bool isBusyCommandComplete() {
|
||||
return !(SDHC_IRQSTAT & (SDHC_IRQSTAT_CC | SDHC_IRQSTAT_CMD_ERROR));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
static bool isBusyCommandInhibit() {
|
||||
return SDHC_PRSSTAT & SDHC_PRSSTAT_CIHB;
|
||||
}
|
||||
static bool isBusyCommandInhibit() { return SDHC_PRSSTAT & SDHC_PRSSTAT_CIHB; }
|
||||
//------------------------------------------------------------------------------
|
||||
static bool isBusyDat() {
|
||||
return SDHC_PRSSTAT & (1 << 24) ? false : true;
|
||||
}
|
||||
static bool isBusyDat() { return SDHC_PRSSTAT & (1 << 24) ? false : true; }
|
||||
//------------------------------------------------------------------------------
|
||||
static bool isBusyDMA() {
|
||||
return m_dmaBusy;
|
||||
}
|
||||
static bool isBusyDMA() { return m_dmaBusy; }
|
||||
//------------------------------------------------------------------------------
|
||||
static bool isBusyFifoRead() {
|
||||
return !(SDHC_PRSSTAT & SDHC_PRSSTAT_BREN);
|
||||
}
|
||||
static bool isBusyFifoRead() { return !(SDHC_PRSSTAT & SDHC_PRSSTAT_BREN); }
|
||||
//------------------------------------------------------------------------------
|
||||
static bool isBusyFifoWrite() {
|
||||
return !(SDHC_PRSSTAT & SDHC_PRSSTAT_BWEN);
|
||||
}
|
||||
static bool isBusyFifoWrite() { return !(SDHC_PRSSTAT & SDHC_PRSSTAT_BWEN); }
|
||||
//------------------------------------------------------------------------------
|
||||
static bool isBusyTransferComplete() {
|
||||
return !(SDHC_IRQSTAT & (SDHC_IRQSTAT_TC | SDHC_IRQSTAT_ERROR));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
static bool rdWrSectors(uint32_t xfertyp,
|
||||
uint32_t sector, uint8_t* buf, size_t n) {
|
||||
static bool rdWrSectors(uint32_t xfertyp, uint32_t sector, uint8_t* buf,
|
||||
size_t n) {
|
||||
if ((3 & (uint32_t)buf) || n == 0) {
|
||||
return sdError(SD_CARD_ERROR_DMA);
|
||||
}
|
||||
@@ -508,10 +550,10 @@ static bool rdWrSectors(uint32_t xfertyp,
|
||||
return sdError(SD_CARD_ERROR_CMD13);
|
||||
}
|
||||
enableDmaIrs();
|
||||
SDHC_DSADDR = (uint32_t)buf;
|
||||
SDHC_DSADDR = (uint32_t)buf;
|
||||
SDHC_BLKATTR = SDHC_BLKATTR_BLKCNT(n) | SDHC_BLKATTR_BLKSIZE(512);
|
||||
SDHC_IRQSIGEN = SDHC_IRQSIGEN_MASK;
|
||||
if (!cardCommand(xfertyp, m_highCapacity ? sector : 512*sector)) {
|
||||
if (!cardCommand(xfertyp, m_highCapacity ? sector : 512 * sector)) {
|
||||
return false;
|
||||
}
|
||||
return waitDmaStatus();
|
||||
@@ -525,7 +567,7 @@ static bool readReg16(uint32_t xfertyp, void* data) {
|
||||
}
|
||||
uint32_t sr[] = {SDHC_CMDRSP0, SDHC_CMDRSP1, SDHC_CMDRSP2, SDHC_CMDRSP3};
|
||||
for (int i = 0; i < 15; i++) {
|
||||
d[14 - i] = sr[i/4] >> 8*(i%4);
|
||||
d[14 - i] = sr[i / 4] >> 8 * (i % 4);
|
||||
}
|
||||
d[15] = 0;
|
||||
return true;
|
||||
@@ -536,16 +578,17 @@ static void setSdclk(uint32_t kHzMax) {
|
||||
const uint32_t SDCLKFS_LIMIT = 0X100;
|
||||
uint32_t dvs = 1;
|
||||
uint32_t sdclkfs = 1;
|
||||
uint32_t maxSdclk = 1000*kHzMax;
|
||||
uint32_t maxSdclk = 1000 * kHzMax;
|
||||
uint32_t base = baseClock();
|
||||
|
||||
while ((base/(sdclkfs*DVS_LIMIT) > maxSdclk) && (sdclkfs < SDCLKFS_LIMIT)) {
|
||||
while ((base / (sdclkfs * DVS_LIMIT) > maxSdclk) &&
|
||||
(sdclkfs < SDCLKFS_LIMIT)) {
|
||||
sdclkfs <<= 1;
|
||||
}
|
||||
while ((base/(sdclkfs*dvs) > maxSdclk) && (dvs < DVS_LIMIT)) {
|
||||
while ((base / (sdclkfs * dvs) > maxSdclk) && (dvs < DVS_LIMIT)) {
|
||||
dvs++;
|
||||
}
|
||||
m_sdClkKhz = base/(1000*sdclkfs*dvs);
|
||||
m_sdClkKhz = base / (1000 * sdclkfs * dvs);
|
||||
sdclkfs >>= 1;
|
||||
dvs--;
|
||||
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
|
||||
@@ -554,11 +597,12 @@ static void setSdclk(uint32_t kHzMax) {
|
||||
#endif // defined(__MK64FX512__) || defined(__MK66FX1M0__)
|
||||
|
||||
// Change dividers.
|
||||
uint32_t sysctl = SDHC_SYSCTL & ~(SDHC_SYSCTL_DTOCV_MASK
|
||||
| SDHC_SYSCTL_DVS_MASK | SDHC_SYSCTL_SDCLKFS_MASK);
|
||||
uint32_t sysctl =
|
||||
SDHC_SYSCTL & ~(SDHC_SYSCTL_DTOCV_MASK | SDHC_SYSCTL_DVS_MASK |
|
||||
SDHC_SYSCTL_SDCLKFS_MASK);
|
||||
|
||||
SDHC_SYSCTL = sysctl | SDHC_SYSCTL_DTOCV(0x0E) | SDHC_SYSCTL_DVS(dvs)
|
||||
| SDHC_SYSCTL_SDCLKFS(sdclkfs);
|
||||
SDHC_SYSCTL = sysctl | SDHC_SYSCTL_DTOCV(0x0E) | SDHC_SYSCTL_DVS(dvs) |
|
||||
SDHC_SYSCTL_SDCLKFS(sdclkfs);
|
||||
|
||||
// Wait until the SDHC clock is stable.
|
||||
while (!(SDHC_PRSSTAT & SDHC_PRSSTAT_SDSTB)) {
|
||||
@@ -667,14 +711,15 @@ bool SdioCard::begin(SdioConfig sdioConfig) {
|
||||
break;
|
||||
}
|
||||
SDHC_SYSCTL |= SDHC_SYSCTL_RSTA;
|
||||
while (SDHC_SYSCTL & SDHC_SYSCTL_RSTA) {}
|
||||
while (SDHC_SYSCTL & SDHC_SYSCTL_RSTA) {
|
||||
}
|
||||
}
|
||||
// Must support 3.2-3.4 Volts
|
||||
arg = m_version2 ? 0X40300000 : 0x00300000;
|
||||
int m = micros();
|
||||
do {
|
||||
if (!cardAcmd(0, ACMD41_XFERTYP, arg) ||
|
||||
((micros() - m) > BUSY_TIMEOUT_MICROS)) {
|
||||
((micros() - m) > BUSY_TIMEOUT_MICROS)) {
|
||||
return sdError(SD_CARD_ERROR_ACMD41);
|
||||
}
|
||||
} while ((SDHC_CMDRSP0 & 0x80000000) == 0);
|
||||
@@ -713,11 +758,13 @@ bool SdioCard::begin(SdioConfig sdioConfig) {
|
||||
if (!cardACMD51(&m_scr)) {
|
||||
return false;
|
||||
}
|
||||
if (!cardACMD13(&m_sds)) {
|
||||
return false;
|
||||
}
|
||||
// Determine if High Speed mode is supported and set frequency.
|
||||
// Check status[16] for error 0XF or status[16] for new mode 0X1.
|
||||
uint8_t status[64];
|
||||
if (m_scr.sdSpec() > 0 &&
|
||||
cardCMD6(0X00FFFFFF, status) && (2 & status[13]) &&
|
||||
if (m_scr.sdSpec() > 0 && cardCMD6(0X00FFFFFF, status) && (2 & status[13]) &&
|
||||
cardCMD6(0X80FFFFF1, status) && (status[16] & 0XF) == 1) {
|
||||
kHzSdClk = 50000;
|
||||
} else {
|
||||
@@ -741,7 +788,7 @@ bool SdioCard::cardCMD6(uint32_t arg, uint8_t* status) {
|
||||
return sdError(SD_CARD_ERROR_CMD13);
|
||||
}
|
||||
enableDmaIrs();
|
||||
SDHC_DSADDR = (uint32_t)status;
|
||||
SDHC_DSADDR = (uint32_t)status;
|
||||
SDHC_BLKATTR = SDHC_BLKATTR_BLKCNT(1) | SDHC_BLKATTR_BLKSIZE(64);
|
||||
SDHC_IRQSIGEN = SDHC_IRQSIGEN_MASK;
|
||||
if (!cardCommand(CMD6_XFERTYP, arg)) {
|
||||
@@ -774,7 +821,7 @@ bool SdioCard::erase(uint32_t firstSector, uint32_t lastSector) {
|
||||
return sdError(SD_CARD_ERROR_CMD32);
|
||||
}
|
||||
if (!cardCommand(CMD33_XFERTYP, lastSector)) {
|
||||
return sdError(SD_CARD_ERROR_CMD33);
|
||||
return sdError(SD_CARD_ERROR_CMD33);
|
||||
}
|
||||
if (!cardCommand(CMD38_XFERTYP, 0)) {
|
||||
return sdError(SD_CARD_ERROR_CMD38);
|
||||
@@ -785,17 +832,11 @@ bool SdioCard::erase(uint32_t firstSector, uint32_t lastSector) {
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
uint8_t SdioCard::errorCode() const {
|
||||
return m_errorCode;
|
||||
}
|
||||
uint8_t SdioCard::errorCode() const { return m_errorCode; }
|
||||
//------------------------------------------------------------------------------
|
||||
uint32_t SdioCard::errorData() const {
|
||||
return m_irqstat;
|
||||
}
|
||||
uint32_t SdioCard::errorData() const { return m_irqstat; }
|
||||
//------------------------------------------------------------------------------
|
||||
uint32_t SdioCard::errorLine() const {
|
||||
return m_errorLine;
|
||||
}
|
||||
uint32_t SdioCard::errorLine() const { return m_errorLine; }
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdioCard::isBusy() {
|
||||
if (m_sdioConfig.useDma()) {
|
||||
@@ -812,7 +853,7 @@ bool SdioCard::isBusy() {
|
||||
m_transferActive = false;
|
||||
stopTransmission(false);
|
||||
return true;
|
||||
#else // defined(__MK64FX512__) || defined(__MK66FX1M0__)
|
||||
#else // defined(__MK64FX512__) || defined(__MK66FX1M0__)
|
||||
return false;
|
||||
#endif // defined(__MK64FX512__) || defined(__MK66FX1M0__)
|
||||
}
|
||||
@@ -821,17 +862,15 @@ bool SdioCard::isBusy() {
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
uint32_t SdioCard::kHzSdClk() {
|
||||
return m_sdClkKhz;
|
||||
}
|
||||
uint32_t SdioCard::kHzSdClk() { return m_sdClkKhz; }
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdioCard::readCID(cid_t* cid) {
|
||||
memcpy(cid, &m_cid, 16);
|
||||
memcpy(cid, &m_cid, sizeof(cid_t));
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdioCard::readCSD(csd_t* csd) {
|
||||
memcpy(csd, &m_csd, 16);
|
||||
memcpy(csd, &m_csd, sizeof(csd_t));
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -849,7 +888,7 @@ bool SdioCard::readData(uint8_t* dst) {
|
||||
if (waitTimeout(isBusyFifoRead)) {
|
||||
return sdError(SD_CARD_ERROR_READ_FIFO);
|
||||
}
|
||||
for (uint32_t iw = 0 ; iw < 512/(4*FIFO_WML); iw++) {
|
||||
for (uint32_t iw = 0; iw < 512 / (4 * FIFO_WML); iw++) {
|
||||
while (0 == (SDHC_PRSSTAT & SDHC_PRSSTAT_BREN)) {
|
||||
}
|
||||
for (uint32_t i = 0; i < FIFO_WML; i++) {
|
||||
@@ -871,7 +910,12 @@ bool SdioCard::readOCR(uint32_t* ocr) {
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdioCard::readSCR(scr_t* scr) {
|
||||
memcpy(scr, &m_scr, 8);
|
||||
memcpy(scr, &m_scr, sizeof(scr_t));
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdioCard::readSDS(sds_t* sds) {
|
||||
memcpy(sds, &m_sds, sizeof(sds_t));
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -931,7 +975,7 @@ bool SdioCard::readSectors(uint32_t sector, uint8_t* dst, size_t n) {
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
if (!readSector(sector + i, dst + i*512UL)) {
|
||||
if (!readSector(sector + i, dst + i * 512UL)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -949,28 +993,22 @@ bool SdioCard::readStart(uint32_t sector) {
|
||||
#if defined(__IMXRT1062__)
|
||||
// Infinite transfer.
|
||||
SDHC_BLKATTR = SDHC_BLKATTR_BLKSIZE(512);
|
||||
#else // defined(__IMXRT1062__)
|
||||
#else // defined(__IMXRT1062__)
|
||||
// Errata - can't do infinite transfer.
|
||||
SDHC_BLKATTR = SDHC_BLKATTR_BLKCNT(MAX_BLKCNT) | SDHC_BLKATTR_BLKSIZE(512);
|
||||
#endif // defined(__IMXRT1062__)
|
||||
|
||||
if (!cardCommand(CMD18_PGM_XFERTYP, m_highCapacity ? sector : 512*sector)) {
|
||||
if (!cardCommand(CMD18_PGM_XFERTYP, m_highCapacity ? sector : 512 * sector)) {
|
||||
return sdError(SD_CARD_ERROR_CMD18);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdioCard::readStop() {
|
||||
return transferStop();
|
||||
}
|
||||
bool SdioCard::readStop() { return transferStop(); }
|
||||
//------------------------------------------------------------------------------
|
||||
uint32_t SdioCard::sectorCount() {
|
||||
return m_csd.capacity();
|
||||
}
|
||||
uint32_t SdioCard::sectorCount() { return m_csd.capacity(); }
|
||||
//------------------------------------------------------------------------------
|
||||
uint32_t SdioCard::status() {
|
||||
return statusCMD13();
|
||||
}
|
||||
uint32_t SdioCard::status() { return statusCMD13(); }
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdioCard::stopTransmission(bool blocking) {
|
||||
m_curState = IDLE_STATE;
|
||||
@@ -998,8 +1036,8 @@ bool SdioCard::syncDevice() {
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
uint8_t SdioCard::type() const {
|
||||
return m_version2 ? m_highCapacity ?
|
||||
SD_CARD_TYPE_SDHC : SD_CARD_TYPE_SD2 : SD_CARD_TYPE_SD1;
|
||||
return m_version2 ? m_highCapacity ? SD_CARD_TYPE_SDHC : SD_CARD_TYPE_SD2
|
||||
: SD_CARD_TYPE_SD1;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdioCard::writeData(const uint8_t* src) {
|
||||
@@ -1016,7 +1054,7 @@ bool SdioCard::writeData(const uint8_t* src) {
|
||||
if (waitTimeout(isBusyFifoWrite)) {
|
||||
return sdError(SD_CARD_ERROR_WRITE_FIFO);
|
||||
}
|
||||
for (uint32_t iw = 0 ; iw < 512/(4*FIFO_WML); iw++) {
|
||||
for (uint32_t iw = 0; iw < 512 / (4 * FIFO_WML); iw++) {
|
||||
while (0 == (SDHC_PRSSTAT & SDHC_PRSSTAT_BWEN)) {
|
||||
}
|
||||
for (uint32_t i = 0; i < FIFO_WML; i++) {
|
||||
@@ -1057,7 +1095,7 @@ bool SdioCard::writeSector(uint32_t sector, const uint8_t* src) {
|
||||
if (!syncDevice()) {
|
||||
return false;
|
||||
}
|
||||
if (!writeStart(sector )) {
|
||||
if (!writeStart(sector)) {
|
||||
return false;
|
||||
}
|
||||
m_curSector = sector;
|
||||
@@ -1087,7 +1125,7 @@ bool SdioCard::writeSectors(uint32_t sector, const uint8_t* src, size_t n) {
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
if (!writeSector(sector + i, src + i*512UL)) {
|
||||
if (!writeSector(sector + i, src + i * 512UL)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1104,17 +1142,15 @@ bool SdioCard::writeStart(uint32_t sector) {
|
||||
#if defined(__IMXRT1062__)
|
||||
// Infinite transfer.
|
||||
SDHC_BLKATTR = SDHC_BLKATTR_BLKSIZE(512);
|
||||
#else // defined(__IMXRT1062__)
|
||||
#else // defined(__IMXRT1062__)
|
||||
// Errata - can't do infinite transfer.
|
||||
SDHC_BLKATTR = SDHC_BLKATTR_BLKCNT(MAX_BLKCNT) | SDHC_BLKATTR_BLKSIZE(512);
|
||||
#endif // defined(__IMXRT1062__)
|
||||
if (!cardCommand(CMD25_PGM_XFERTYP, m_highCapacity ? sector : 512*sector)) {
|
||||
if (!cardCommand(CMD25_PGM_XFERTYP, m_highCapacity ? sector : 512 * sector)) {
|
||||
return sdError(SD_CARD_ERROR_CMD25);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdioCard::writeStop() {
|
||||
return transferStop();
|
||||
}
|
||||
bool SdioCard::writeStop() { return transferStop(); }
|
||||
#endif // defined(__MK64FX512__) defined(__MK66FX1M0__) defined(__IMXRT1062__)
|
||||
|
||||
Reference in New Issue
Block a user