|
|
|
|
|
|
|
|
}
|
|
|
}
|
|
|
/** SPI send multiple bytes */
|
|
|
/** SPI send multiple bytes */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#elif defined(__IMXRT1052__) || defined(__IMXRT1062__)
|
|
|
|
|
|
#define USE_TEENSY4_SPI
|
|
|
|
|
|
|
|
|
|
|
|
static void spiInit(uint8_t spiRate) {
|
|
|
|
|
|
switch (spiRate) {
|
|
|
|
|
|
// the top 2 speeds are set to 24 MHz, for the SD library defaults
|
|
|
|
|
|
case 0: settings = SPISettings(25000000, MSBFIRST, SPI_MODE0); break;
|
|
|
|
|
|
case 1: settings = SPISettings(24000000, MSBFIRST, SPI_MODE0); break;
|
|
|
|
|
|
case 2: settings = SPISettings(8000000, MSBFIRST, SPI_MODE0); break;
|
|
|
|
|
|
case 3: settings = SPISettings(4000000, MSBFIRST, SPI_MODE0); break;
|
|
|
|
|
|
case 4: settings = SPISettings(3000000, MSBFIRST, SPI_MODE0); break;
|
|
|
|
|
|
case 5: settings = SPISettings(2000000, MSBFIRST, SPI_MODE0); break;
|
|
|
|
|
|
default: settings = SPISettings(400000, MSBFIRST, SPI_MODE0);
|
|
|
|
|
|
}
|
|
|
|
|
|
SPI.begin();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void spiSend(uint8_t b) {
|
|
|
|
|
|
SPI.transfer(b);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static uint8_t spiRec(void) {
|
|
|
|
|
|
return SPI.transfer(0xff);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void spiRec(uint8_t* buf, size_t len) {
|
|
|
|
|
|
SPI.transfer(buf, len);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void spiRecIgnore(size_t len) {
|
|
|
|
|
|
for (size_t i=0; i < len; i++)
|
|
|
|
|
|
SPI.transfer(0xff);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
//------------------------------------------------------------------------------
|
|
|
#else
|
|
|
#else
|
|
|
// functions for hardware SPI
|
|
|
// functions for hardware SPI
|
|
|
|
|
|
|
|
|
pinMode(chipSelectPin_, OUTPUT);
|
|
|
pinMode(chipSelectPin_, OUTPUT);
|
|
|
digitalWrite(chipSelectPin_, HIGH);
|
|
|
digitalWrite(chipSelectPin_, HIGH);
|
|
|
|
|
|
|
|
|
#ifdef USE_TEENSY3_SPI
|
|
|
|
|
|
|
|
|
#if defined(USE_TEENSY3_SPI)
|
|
|
spiBegin();
|
|
|
spiBegin();
|
|
|
spiInit(6);
|
|
|
spiInit(6);
|
|
|
|
|
|
#elif defined(USE_TEENSY4_SPI)
|
|
|
|
|
|
spiInit(6);
|
|
|
|
|
|
pinMode(SS_PIN, OUTPUT);
|
|
|
|
|
|
digitalWrite(SS_PIN, HIGH); // disable any SPI device using hardware SS pin
|
|
|
#else
|
|
|
#else
|
|
|
// set pin modes
|
|
|
// set pin modes
|
|
|
pinMode(SPI_MISO_PIN, INPUT);
|
|
|
pinMode(SPI_MISO_PIN, INPUT);
|
|
|
|
|
|
|
|
|
settings = SPISettings(250000, MSBFIRST, SPI_MODE0);
|
|
|
settings = SPISettings(250000, MSBFIRST, SPI_MODE0);
|
|
|
#endif
|
|
|
#endif
|
|
|
#endif // not USE_TEENSY3_SPI
|
|
|
#endif // not USE_TEENSY3_SPI
|
|
|
|
|
|
|
|
|
// must supply min of 74 clock cycles with CS high.
|
|
|
// must supply min of 74 clock cycles with CS high.
|
|
|
#ifdef SPI_HAS_TRANSACTION
|
|
|
#ifdef SPI_HAS_TRANSACTION
|
|
|
SPI.beginTransaction(settings);
|
|
|
SPI.beginTransaction(settings);
|
|
|
|
|
|
|
|
|
#ifdef SPI_HAS_TRANSACTION
|
|
|
#ifdef SPI_HAS_TRANSACTION
|
|
|
SPI.endTransaction();
|
|
|
SPI.endTransaction();
|
|
|
#endif
|
|
|
#endif
|
|
|
|
|
|
|
|
|
chipSelectLow();
|
|
|
chipSelectLow();
|
|
|
|
|
|
|
|
|
// command to go idle in SPI mode
|
|
|
// command to go idle in SPI mode
|
|
|
while ((status_ = cardCommand(CMD0, 0)) != R1_IDLE_STATE) {
|
|
|
while ((status_ = cardCommand(CMD0, 0)) != R1_IDLE_STATE) {
|
|
|
unsigned int d = millis() - t0;
|
|
|
unsigned int d = millis() - t0;
|
|
|
|
|
|
|
|
|
}
|
|
|
}
|
|
|
// 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
|
|
|
unsigned int d = millis() - t0;
|
|
|
unsigned int d = millis() - t0;
|
|
|
|
|
|
|
|
|
if (!waitStartBlock()) {
|
|
|
if (!waitStartBlock()) {
|
|
|
goto fail;
|
|
|
goto fail;
|
|
|
}
|
|
|
}
|
|
|
#ifdef USE_TEENSY3_SPI
|
|
|
|
|
|
|
|
|
#if defined(USE_TEENSY3_SPI) | defined(USE_TEENSY4_SPI)
|
|
|
spiRec(dst, 512);
|
|
|
spiRec(dst, 512);
|
|
|
spiRecIgnore(2);
|
|
|
spiRecIgnore(2);
|
|
|
#else // OPTIMIZE_HARDWARE_SPI
|
|
|
#else // OPTIMIZE_HARDWARE_SPI
|
|
|
|
|
|
|
|
|
* false, is returned for an invalid value of \a sckRateID.
|
|
|
* false, is returned for an invalid value of \a sckRateID.
|
|
|
*/
|
|
|
*/
|
|
|
uint8_t Sd2Card::setSckRate(uint8_t sckRateID) {
|
|
|
uint8_t Sd2Card::setSckRate(uint8_t sckRateID) {
|
|
|
#ifdef USE_TEENSY3_SPI
|
|
|
|
|
|
|
|
|
#if defined(USE_TEENSY3_SPI) || defined(USE_TEENSY4_SPI)
|
|
|
spiInit(sckRateID);
|
|
|
spiInit(sckRateID);
|
|
|
return true;
|
|
|
return true;
|
|
|
#else
|
|
|
#else
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
//------------------------------------------------------------------------------
|
|
|
// send one block of data for write block or write multiple blocks
|
|
|
// send one block of data for write block or write multiple blocks
|
|
|
uint8_t Sd2Card::writeData(uint8_t token, const uint8_t* src) {
|
|
|
uint8_t Sd2Card::writeData(uint8_t token, const uint8_t* src) {
|
|
|
#ifdef OPTIMIZE_HARDWARE_SPI
|
|
|
|
|
|
|
|
|
#if defined(OPTIMIZE_HARDWARE_SPI) && !defined(USE_TEENSY4_SPI)
|
|
|
|
|
|
|
|
|
// send data - optimized loop
|
|
|
// send data - optimized loop
|
|
|
SPDR = token;
|
|
|
SPDR = token;
|
|
|
|
|
|
|
|
|
#else // OPTIMIZE_HARDWARE_SPI
|
|
|
#else // OPTIMIZE_HARDWARE_SPI
|
|
|
spiSend(token);
|
|
|
spiSend(token);
|
|
|
for (uint16_t i = 0; i < 512; i++) {
|
|
|
for (uint16_t i = 0; i < 512; i++) {
|
|
|
spiSend(src[i]);
|
|
|
|
|
|
|
|
|
spiSend(src[i]);
|
|
|
}
|
|
|
}
|
|
|
#endif // OPTIMIZE_HARDWARE_SPI
|
|
|
#endif // OPTIMIZE_HARDWARE_SPI
|
|
|
spiSend(0xff); // dummy crc
|
|
|
spiSend(0xff); // dummy crc
|