//------------------------------------------------------------------------------ // send command to card uint8_t SdReader::cardCommand(uint8_t cmd, uint32_t arg) { //Serial.print("cardCommand, cmd="); Serial.print(cmd, DEC); Serial.print(", arg="); Serial.println(arg, DEC); uint8_t r1; // end read if in partialBlockRead mode readEnd(); // select card spiSSLow(); // wait up to 300 ms if busy waitNotBusy(300); // send command spiSend(cmd | 0x40); // send argument for (int8_t s = 24; s >= 0; s -= 8) spiSend(arg >> s); // send CRC uint8_t crc = 0XFF; if (cmd == CMD0) crc = 0X95; // correct crc for CMD0 with arg 0 if (cmd == CMD8) crc = 0X87; // correct crc for CMD8 with arg 0X1AA spiSend(crc); // wait for response for (uint8_t retry = 0; ((r1 = spiRec()) & 0X80) && retry != 0XFF; retry++); return r1; }
/** * Initialize a SD flash memory card. * * \param[in] slow Set SPI Frequency F_CPU/4 if true else F_CPU/2. * * \return The value one, true, is returned for success and * the value zero, false, is returned for failure. * */ uint8_t SdCard::init(uint8_t slow) { pinMode(SS, OUTPUT); spiSSHigh(); pinMode(MOSI, OUTPUT); pinMode(SCK, OUTPUT); //Enable SPI, Master, clock rate F_CPU/128 SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0); //must supply min of 74 clock cycles with CS high. for (uint8_t i = 0; i < 10; i++) spiSend(0XFF); spiSSLow(); // next line prevent re-init hang by some cards (not sure why this works) for (uint16_t i = 0; i <= 512; i++) spiRec(); uint8_t r = cardCommand(CMD0, 0); for (uint16_t retry = 0; r != R1_IDLE_STATE; retry++){ if (retry == 10000) { error(SD_ERROR_CMD0, r); return false; } r = spiRec(); } for (uint16_t retry = 0; ; retry++) { cardCommand(CMD55, 0); if ((r = cardCommand(ACMD41, 0)) == R1_READY_STATE)break; if (retry == 1000) { error(SD_ERROR_ACMD41, r); return false; } } // set SPI frequency SPCR &= ~((1 << SPR1) | (1 << SPR0)); // F_CPU/4 if (!slow) SPSR |= (1 << SPI2X); // Doubled Clock Frequency to F_CPU/2 spiSSHigh(); return true; }
//------------------------------------------------------------------------------ // send command to card uint8_t sdCardCommand(uint8_t cmd, uint32_t arg) { uint8_t r1; uint8_t retry; signed char s; // end read if in partialBlockRead mode sdReadEnd(); // select card spiSSLow(); // wait up to 300 ms if busy sdWaitNotBusy(300); // send command spiSend(cmd | 0x40); // send argument for (s = 24; s >= 0; s -= 8) spiSend(arg >> s); // send CRC uint8_t crc = 0XFF; if (cmd == CMD0) crc = 0X95; // correct crc for CMD0 with arg 0 if (cmd == CMD8) crc = 0X87; // correct crc for CMD8 with arg 0X1AA spiSend(crc); // wait for response for (retry = 0; ((r1 = spiRec()) & 0X80) && retry != 0XFF; retry++); return r1; }
//------------------------------------------------------------------------------ static uint8_t cardCommand(uint8_t cmd, uint32_t arg) { uint8_t r1; // some cards need extra clocks after transaction to go to ready state // easiest to put extra clocks before next transaction spiSSLow(); spiRec(); spiSend(cmd | 0x40); for (int8_t s = 24; s >= 0; s -= 8) spiSend(arg >> s); spiSend(cmd == CMD0 ? 0x95 : 0XFF);//must send valid CRC for CMD0 //wait for not busy for (uint8_t retry = 0; (r1 = spiRec()) == 0xFF && retry != 0XFF; retry++); return r1; }
/** * Initialize a SD flash memory card. * * \param[in] slow If \a slow is false (zero) the SPI bus will * be initialize at a speed of 8 Mhz. If \a slow is true (nonzero) * the SPI bus will be initialize a speed of 4 Mhz. This may be helpful * for some SD cards with Version 1.0 of the Adafruit Wave Shield. * * \return The value one, true, is returned for success and * the value zero, false, is returned for failure. * */ uint8_t SdReader::init(uint8_t slow) { uint8_t ocr[4]; uint8_t r; pinMode(SS, OUTPUT); digitalWrite(SS, HIGH); pinMode(MOSI, OUTPUT); pinMode(MISO_PIN, INPUT); pinMode(SCK, OUTPUT); #if SPI_INIT_SLOW // Enable SPI, Master, clock rate f_osc/128 SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0); #else // SPI_INIT_SLOW // Enable SPI, Master, clock rate f_osc/64 SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR1); #endif // SPI_INIT_SLOW // must supply min of 74 clock cycles with CS high. for (uint8_t i = 0; i < 10; i++) spiSend(0XFF); // next two lines prevent re-init hang by cards that were in partial read spiSSLow(); for (uint16_t i = 0; i <= 512; i++) spiRec(); // command to go idle in SPI mode for (uint8_t retry = 0; ; retry++) { if ((r = cardCommand(CMD0, 0)) == R1_IDLE_STATE) break; if (retry == 10) { error(SD_CARD_ERROR_CMD0, r); return false; } } // check SD version r = cardCommand(CMD8, 0x1AA); if (r == R1_IDLE_STATE) { for(uint8_t i = 0; i < 4; i++) { r = spiRec(); } if (r != 0XAA) { error(SD_CARD_ERROR_CMD8_ECHO, r); return false; } type(SD_CARD_TYPE_SD2); } else if (r & R1_ILLEGAL_COMMAND) { type(SD_CARD_TYPE_SD1); } else { error(SD_CARD_ERROR_CMD8, r); } // initialize card and send host supports SDHC if SD2 for (uint16_t t0 = millis();;) { cardCommand(CMD55, 0); r = cardCommand(ACMD41, type() == SD_CARD_TYPE_SD2 ? 0X40000000 : 0); if (r == R1_READY_STATE) break; // timeout after 2 seconds if (((uint16_t)millis() - t0) > 2000) { error(SD_CARD_ERROR_ACMD41); return false; } } // if SD2 read OCR register to check for SDHC card if (type() == SD_CARD_TYPE_SD2) { if(cardCommand(CMD58, 0)) { error(SD_CARD_ERROR_CMD58); return false; } if ((spiRec() & 0XC0) == 0XC0) type(SD_CARD_TYPE_SDHC); // discard rest of ocr for (uint8_t i = 0; i < 3; i++) spiRec(); } // use max SPI frequency unless slow is true SPCR &= ~((1 << SPR1) | (1 << SPR0)); // f_OSC/4 if (!slow) SPSR |= (1 << SPI2X); // Doubled Clock Frequency: f_OSC/2 spiSSHigh(); return true; }
/** * Initialize a SD flash memory card. * * \param[in] slow Set SPI Frequency F_CPU/4 if true else F_CPU/2. * * \return The value one, true, is returned for success and * the value zero, false, is returned for failure. */ uint8_t Sd2Card::init(uint8_t slow) { uint8_t r; errorCode_ = inBlock_ = partialBlockRead_ = type_ = 0; // set pin modes spiSSOutputMode(); spiSSHigh(); spiMISOInputMode(); spiMOSIOutputMode(); spiSCKOutputMode(); #ifndef SOFTWARE_SPI //Enable SPI, Master, clock rate f_osc/128 SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0); #endif //SOFTWARE_SPI //must supply min of 74 clock cycles with CS high. for (uint8_t i = 0; i < 10; i++) spiSend(0XFF); // next two lines prevent re-init hang by cards that were in partial read spiSSLow(); for (uint16_t i = 0; i <= 512; i++) spiRec(); // command to go idle in SPI mode for (uint8_t retry = 0; ; retry++) { if ((r = cardCommand(CMD0, 0)) == R1_IDLE_STATE) break; if (retry == 10) { error(SD_CARD_ERROR_CMD0, r); return false; } } // check SD version if ((cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND)) { type(SD_CARD_TYPE_SD1); } else { // only need last byte of r7 response for(uint8_t i = 0; i < 4; i++) r = spiRec(); if (r != 0XAA) { error(SD_CARD_ERROR_CMD8, r); return false; } type(SD_CARD_TYPE_SD2); } // initialize card and send host supports SDHC if SD2 for (uint16_t t0 = millis();;) { r = cardAcmd(ACMD41, type() == SD_CARD_TYPE_SD2 ? 0X40000000 : 0); if (r == R1_READY_STATE) break; // timeout after 2 seconds if (((uint16_t)millis() - t0) > 2000) { error(SD_CARD_ERROR_ACMD41); return false; } } // if SD2 read OCR register to check for SDHC card if (type() == SD_CARD_TYPE_SD2) { if(cardCommand(CMD58, 0)) { error(SD_CARD_ERROR_CMD58); return false; } if ((spiRec() & 0XC0) == 0XC0) type(SD_CARD_TYPE_SDHC); // discard rest of ocr for (uint8_t i = 0; i < 3; i++) spiRec(); } #ifndef SOFTWARE_SPI // set SPI frequency to f_OSC/4 SPCR &= ~((1 << SPR1) | (1 << SPR0)); // if !slow set SPI frequency to f_OSC/2 if (!slow) SPSR |= (1 << SPI2X); #endif // SOFTWARE_SPI spiSSHigh(); return true; }