Skip to content

Commit

Permalink
fix(sdmmc): use correct argument for ACMD41 in SPI mode
Browse files Browse the repository at this point in the history
ACMD41 argument is different between SD mode and SPI mode.
In SPI mode, the only non-zero bit may be the HCS bit. Unlike the SD
mode, the bits reflecting the host's OCR should be zero.
Previously, we used to set these bits the same way as for the SD mode.
This has caused certain cards to fail initializing, apparently their
controllers have checked the ACMD41 argument more strictly and refused
to finish initialization, resulting in an error such as

    sdmmc_common: sdmmc_init_ocr: send_op_cond (1) returned 0x107

(Note that this error may have other causes than the one fixed in
this commit. For example, if the card doesn't have a sufficient and
stable power supply, it may also fail to complete the internal
initialization process, and will never clear the busy flag in R1
response.)

Closes #6686
Closes #10542
  • Loading branch information
igrr committed Feb 28, 2024
1 parent 12de460 commit 47ba4d6
Showing 1 changed file with 13 additions and 3 deletions.
16 changes: 13 additions & 3 deletions components/sdmmc/sdmmc_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,27 @@ esp_err_t sdmmc_init_ocr(sdmmc_card_t* card)
*/

uint32_t host_ocr = get_host_ocr(card->host.io_voltage);

/* In SPI mode, the only non-zero bit of ACMD41 is HCS (bit 30)
* In SD mode, bits 23:8 contain the supported voltage mask
*/
uint32_t acmd41_arg = 0;
if (!host_is_spi(card)) {
acmd41_arg = host_ocr;
}

if ((card->ocr & SD_OCR_SDHC_CAP) != 0) {
host_ocr |= SD_OCR_SDHC_CAP;
acmd41_arg |= SD_OCR_SDHC_CAP;
}

/* Send SEND_OP_COND (ACMD41) command to the card until it becomes ready. */
err = sdmmc_send_cmd_send_op_cond(card, host_ocr, &card->ocr);
err = sdmmc_send_cmd_send_op_cond(card, acmd41_arg, &card->ocr);

/* If time-out, re-try send_op_cond as MMC */
if (err == ESP_ERR_TIMEOUT && !host_is_spi(card)) {
ESP_LOGD(TAG, "send_op_cond timeout, trying MMC");
card->is_mmc = 1;
err = sdmmc_send_cmd_send_op_cond(card, host_ocr, &card->ocr);
err = sdmmc_send_cmd_send_op_cond(card, acmd41_arg, &card->ocr);
}

if (err != ESP_OK) {
Expand Down

0 comments on commit 47ba4d6

Please sign in to comment.