You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Using information from here and here I am having difficulty setting my UHS-1, Type 2 cards into high voltage mode.
Presumably, this step should be accomplished when sending 0x40000000 during ACMD41, but that does not seem to be the case. In fact, according to the SD protocol, the upper 8 bits are ignored when the lower 24 bits are 0. So does this command even have any effect here? What should the value be instead?
Secondly, it asserts that some cards already require CRC. So I updated the CRC portion of cardCommand() to be:
// 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
if (cmd == CMD1) crc = 0xF9;
//if (cmd == ACMD41) crc = 0x77; //correct crc for ACMD41 with arg 0x40000000
if (cmd == ACMD41) crc = 0x17; //correct crc for ACMD41 with arg 0x50000000
if (cmd == CMD58) crc = 0xFD;
spiSend(crc);
Lastly, it recommends sending a dummy byte before CMD0 (aside from the 74 clock pulses), therefore I begin the function:
uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) {
// end read if in partialBlockRead mode
readEnd();
// select card
chipSelectLow();
// wait up to 300 ms if busy
waitNotBusy(300);
//send dummy byte before idle
if (cmd == CMD0) spiSend(0xFF);
// send command
spiSend(cmd | 0x40);
...
But for some reason, my cards always remain in low voltage (1.8V) mode, despite being purportedly capable of 2.7-3.3V operation (as evidenced in the OCR).
My full ::init() function looks like this:
uint8_t Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {
errorCode_ = inBlock_ = partialBlockRead_ = type_ = 0;
chipSelectPin_ = chipSelectPin;
// 16-bit init start time allows over a minute
unsigned int t0 = millis();
uint32_t arg;
// set pin modes
pinMode(chipSelectPin_, OUTPUT);
digitalWrite(chipSelectPin_, HIGH);
/* Drive the MISO pin high */
pinMode(SPI_MISO_PIN, OUTPUT);
digitalWrite(SPI_MISO_PIN, HIGH);
#ifndef USE_SPI_LIB
pinMode(SPI_MISO_PIN, INPUT);
pinMode(SPI_MOSI_PIN, OUTPUT);
pinMode(SPI_SCK_PIN, OUTPUT);
#endif
#ifndef SOFTWARE_SPI
#ifndef USE_SPI_LIB
// SS must be in output mode even it is not chip select
pinMode(SS_PIN, OUTPUT);
digitalWrite(SS_PIN, HIGH); // disable any SPI device using hardware SS pin
// Enable SPI, Master, clock rate f_osc/128
SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0);
// clear double speed
SPSR &= ~(1 << SPI2X);
#else // USE_SPI_LIB
SDCARD_SPI.begin();
settings = SPISettings(350000, MSBFIRST, SPI_MODE0);
#endif // USE_SPI_LIB
#endif // SOFTWARE_SPI
// must supply min of 74 clock cycles with CS high.
#ifdef USE_SPI_LIB
SDCARD_SPI.beginTransaction(settings);
#endif
for (uint8_t i = 0; i < 10; i++) spiSend(0XFF);
#ifdef USE_SPI_LIB
SDCARD_SPI.endTransaction();
#endif
chipSelectLow();
//Send CMD0
// command to go idle in SPI mode
while ((status_ = cardCommand(CMD0, 0)) != R1_IDLE_STATE) {
unsigned int d = millis() - t0;
if (d > SD_INIT_TIMEOUT) {
error(SD_CARD_ERROR_CMD0);
goto fail;
}
}
//Send CMD8
// 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++) status_ = spiRec();
if (status_ != 0XAA) {
if(status_ != 0x01){
error(SD_CARD_ERROR_CMD8);
goto fail;
}
}
type(SD_CARD_TYPE_SD2);
}
//SDHC supported, SDXC maximum performance
arg = type() == SD_CARD_TYPE_SD2 ? 0X50000000 : 0;
while ((status_ = cardAcmd(ACMD41, arg)) != R1_READY_STATE) {
// check for timeout
unsigned int d = millis() - t0;
if (d > SD_INIT_TIMEOUT) {
break;
}
}
/*Try CMD1 before trying ACMD41 again */
if(status_){
while ((status_ = cardCommand(CMD1, 0)) != R1_READY_STATE) {
unsigned int d = millis() - t0;
if (d > SD_INIT_TIMEOUT) {
error(SD_CARD_ERROR_CMD0);
goto fail;
}
}
while ((status_ = cardAcmd(ACMD41, arg)) != R1_READY_STATE) {
// check for timeout
unsigned int d = millis() - t0;
if (d > SD_INIT_TIMEOUT) {
error(SD_CARD_ERROR_ACMD41);
goto fail;
}
}
}
// command to initialize in SPI mode
// initialize card and send host supports SDHC if SD2
// if SD2 read OCR register to check for SDHC card
if (type() == SD_CARD_TYPE_SD2) {
if ((status_ = cardCommand(CMD58, 0))) {
error(SD_CARD_ERROR_CMD58);
goto fail;
}
if ((spiRec() & 0XC0) == 0XC0) type(SD_CARD_TYPE_SDHC);
// discard rest of ocr - contains allowed voltage range
for (uint8_t i = 0; i < 3; i++) spiRec();
}
chipSelectHigh();
#ifndef SOFTWARE_SPI
return setSckRate(sckRateID);
#else // SOFTWARE_SPI
return true;
#endif // SOFTWARE_SPI
fail:
chipSelectHigh();
return false;
}
The text was updated successfully, but these errors were encountered:
Using information from here and here I am having difficulty setting my UHS-1, Type 2 cards into high voltage mode.
Presumably, this step should be accomplished when sending 0x40000000 during ACMD41, but that does not seem to be the case. In fact, according to the SD protocol, the upper 8 bits are ignored when the lower 24 bits are 0. So does this command even have any effect here? What should the value be instead?
Secondly, it asserts that some cards already require CRC. So I updated the CRC portion of cardCommand() to be:
Lastly, it recommends sending a dummy byte before CMD0 (aside from the 74 clock pulses), therefore I begin the function:
But for some reason, my cards always remain in low voltage (1.8V) mode, despite being purportedly capable of 2.7-3.3V operation (as evidenced in the OCR).
My full ::init() function looks like this:
The text was updated successfully, but these errors were encountered: