Merge branch 'fix/sdmmc_sdspi_retry_crc_check_v6.0' into 'release/v6.0'

fix(sdspi): 0x106 error during SD card init via SPI related fixes (v6.0)

See merge request espressif/esp-idf!45691
This commit is contained in:
Jiang Jiang Jian
2026-03-20 10:51:38 +08:00
6 changed files with 55 additions and 3 deletions
@@ -1,9 +1,10 @@
/*
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stddef.h>
#include <string.h>
#include "unity.h"
#include "sdmmc_cmd.h"
#include "sdmmc_test_begin_end_spi.h"
@@ -47,3 +48,38 @@ TEST_CASE("sdspi probe, slot 1, HS", "[sdspi]")
//here freq should be changed to SDMMC_FREQ_HIGHSPEED after fixing IDF-8749
do_one_sdspi_probe(SLOT_1, SDMMC_FREQ_DEFAULT);
}
static void do_one_sdspi_probe_ignore_crc(int slot, int freq_khz)
{
sdmmc_card_t card;
sdmmc_test_spi_skip_if_board_incompatible(slot, freq_khz);
sdmmc_host_t config = SDSPI_HOST_DEFAULT();
config.flags |= SDMMC_HOST_FLAG_SPI_IGNORE_DATA_CRC;
sdmmc_test_spi_begin(slot, freq_khz, &card, &config, NULL, NULL);
sdmmc_card_print_info(stdout, &card);
size_t sector_size = card.csd.sector_size;
uint8_t* buffer = heap_caps_calloc(sector_size, 1, MALLOC_CAP_DMA);
TEST_ESP_OK(sdmmc_read_sectors(&card, buffer, 0, 1));
uint8_t* w_buffer = heap_caps_calloc(sector_size, 1, MALLOC_CAP_DMA);
memset(w_buffer, 0xAB, sector_size);
int k = 10; // write every k sectors
for (int i = 0; i < 30; i += sector_size * k) {
memset(buffer, 0, sector_size);
TEST_ESP_OK(sdmmc_write_sectors(&card, w_buffer, i, 1));
TEST_ESP_OK(sdmmc_read_sectors(&card, buffer, i, 1));
TEST_ASSERT_TRUE(memcmp(buffer, w_buffer, sector_size) == 0);
}
free(w_buffer);
free(buffer);
sdmmc_test_spi_end(slot, &card);
}
TEST_CASE("sdspi probe, slot 0, disabled crc check", "[sdspi]")
{
do_one_sdspi_probe_ignore_crc(SLOT_0, SDMMC_FREQ_DEFAULT);
}
TEST_CASE("sdspi probe, slot 1, disabled crc check", "[sdspi]")
{
do_one_sdspi_probe_ignore_crc(SLOT_1, SDMMC_FREQ_DEFAULT);
}
@@ -33,6 +33,7 @@ extern "C" {
#define SDMMC_GO_IDLE_DELAY_MS 20
#define SDMMC_IO_SEND_OP_COND_DELAY_MS 10
#define SDMMC_INIT_SPI_CRC_RETRY_DELAY_MS 10
#define SDMMC_INIT_WAIT_DATA_READY_TIMEOUT_US (5000 * 1000)
#define SDMMC_READY_FOR_DATA_TIMEOUT_US (5000 * 1000)
@@ -191,6 +191,9 @@ typedef struct {
Currently this is only used by the SDIO driver. Set this flag when
using SDIO CMD53 byte mode, with user buffer that is behind the cache
or not aligned to 4 byte boundary. */
#define SDMMC_HOST_FLAG_SPI_IGNORE_DATA_CRC \
BIT(7) /*!< SPI mode only: Do not enable CRC verification (skip CMD59).
Not recommended as it disables data integrity checking. */
int slot; /*!< slot number, to be passed to host functions */
int max_freq_khz; /*!< max frequency supported by the host */
#define SDMMC_FREQ_DEFAULT 20000 /*!< SD/MMC Default speed (limited by clock divider) */
+4
View File
@@ -384,6 +384,10 @@ esp_err_t sdmmc_fix_host_flags(sdmmc_card_t* card)
}
}
if (card->host.flags & SDMMC_HOST_FLAG_SPI_IGNORE_DATA_CRC) {
ESP_LOGW(TAG, "SDMMC_HOST_FLAG_SPI_IGNORE_DATA_CRC flag is set on non-SPI host");
}
#if !SOC_SDMMC_UHS_I_SUPPORTED
if ((card->host.max_freq_khz == SDMMC_FREQ_SDR50) ||
(card->host.max_freq_khz == SDMMC_FREQ_DDR50) ||
+5 -2
View File
@@ -93,9 +93,12 @@ esp_err_t sdmmc_card_init(const sdmmc_host_t* config, sdmmc_card_t* card)
const bool is_mem = card->is_mem;
const bool is_sdio = !is_mem;
const bool ignore_data_crc = (config->flags & SDMMC_HOST_FLAG_SPI_IGNORE_DATA_CRC);
/* Enable CRC16 checks for data transfers in SPI mode */
SDMMC_INIT_STEP(is_spi, sdmmc_init_spi_crc);
if (!ignore_data_crc) {
/* Enable CRC16 checks for data transfers in SPI mode */
SDMMC_INIT_STEP(is_spi, sdmmc_init_spi_crc);
}
/* Use SEND_OP_COND to set up card OCR */
SDMMC_INIT_STEP(is_mem, sdmmc_init_ocr);
+5
View File
@@ -643,6 +643,11 @@ esp_err_t sdmmc_init_spi_crc(sdmmc_card_t* card)
*/
assert(host_is_spi(card));
esp_err_t err = sdmmc_send_cmd_crc_on_off(card, true);
if (err == ESP_ERR_NOT_SUPPORTED) { // Some cards fail to enable CRC on the first try, trying again
ESP_LOGD(TAG, "%s: enabling CRC failed with 0x%x, trying again", __func__, err);
vTaskDelay(SDMMC_INIT_SPI_CRC_RETRY_DELAY_MS / portTICK_PERIOD_MS);
err = sdmmc_send_cmd_crc_on_off(card, true);
}
if (err != ESP_OK) {
ESP_LOGE(TAG, "%s: sdmmc_send_cmd_crc_on_off returned 0x%x", __func__, err);
return err;