From 3f838d7843835215334faddd0c22add48a4657fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20M=C3=BAdry?= Date: Tue, 15 Oct 2024 22:28:26 +0200 Subject: [PATCH 1/2] fix(sdmmc): Improve SD card state checking after write/read command --- components/sdmmc/include/sd_protocol_defs.h | 3 ++- components/sdmmc/sdmmc_cmd.c | 9 +++++++-- components/sdmmc/sdmmc_mmc.c | 4 ++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/components/sdmmc/include/sd_protocol_defs.h b/components/sdmmc/include/sd_protocol_defs.h index a1b6a8ec022..f3252be38fc 100644 --- a/components/sdmmc/include/sd_protocol_defs.h +++ b/components/sdmmc/include/sd_protocol_defs.h @@ -108,6 +108,7 @@ extern "C" { #define MMC_R1_CURRENT_STATE_POS (9) #define MMC_R1_CURRENT_STATE_MASK (0x1E00)/* card current state */ #define MMC_R1_CURRENT_STATE_TRAN (4) +#define MMC_R1_CURRENT_STATE_STATUS(status) ((status & MMC_R1_CURRENT_STATE_MASK) >> MMC_R1_CURRENT_STATE_POS) /* SPI mode R1 response type bits */ #define SD_SPI_R1_IDLE_STATE (1<<0) @@ -424,7 +425,7 @@ extern "C" { * * 67 45 23 01 ef cd ab 89 * - * MMC_RSP_BITS will extact bits as follows: + * MMC_RSP_BITS will extract bits as follows: * * start=0 len=4 -> result=0x00000007 * start=0 len=12 -> result=0x00000567 diff --git a/components/sdmmc/sdmmc_cmd.c b/components/sdmmc/sdmmc_cmd.c index fb18a9d6962..24acb6cb4a0 100644 --- a/components/sdmmc/sdmmc_cmd.c +++ b/components/sdmmc/sdmmc_cmd.c @@ -444,6 +444,11 @@ esp_err_t sdmmc_write_sectors(sdmmc_card_t* card, const void* src, return err; } +static bool mmc_ready_for_data(uint32_t status) +{ + return (status & MMC_R1_READY_FOR_DATA) && (MMC_R1_CURRENT_STATE_STATUS(status) == MMC_R1_CURRENT_STATE_TRAN); +} + esp_err_t sdmmc_write_sectors_dma(sdmmc_card_t* card, const void* src, size_t start_block, size_t block_count, size_t buffer_len) { @@ -480,7 +485,7 @@ esp_err_t sdmmc_write_sectors_dma(sdmmc_card_t* card, const void* src, int64_t t0 = esp_timer_get_time(); int64_t t1 = 0; /* SD mode: wait for the card to become idle based on R1 status */ - while (!host_is_spi(card) && !(status & MMC_R1_READY_FOR_DATA)) { + while (!host_is_spi(card) && !mmc_ready_for_data(status)) { t1 = esp_timer_get_time(); if (t1 - t0 > SDMMC_READY_FOR_DATA_TIMEOUT_US) { ESP_LOGE(TAG, "write sectors dma - timeout"); @@ -602,7 +607,7 @@ esp_err_t sdmmc_read_sectors_dma(sdmmc_card_t* card, void* dst, int64_t t0 = esp_timer_get_time(); int64_t t1 = 0; /* SD mode: wait for the card to become idle based on R1 status */ - while (!host_is_spi(card) && !(status & MMC_R1_READY_FOR_DATA)) { + while (!host_is_spi(card) && !mmc_ready_for_data(status)) { t1 = esp_timer_get_time(); if (t1 - t0 > SDMMC_READY_FOR_DATA_TIMEOUT_US) { ESP_LOGE(TAG, "read sectors dma - timeout"); diff --git a/components/sdmmc/sdmmc_mmc.c b/components/sdmmc/sdmmc_mmc.c index e3f44bc865b..23f18272f41 100644 --- a/components/sdmmc/sdmmc_mmc.c +++ b/components/sdmmc/sdmmc_mmc.c @@ -272,8 +272,8 @@ esp_err_t sdmmc_init_mmc_check_ext_csd(sdmmc_card_t* card) ESP_LOGE(TAG, "%s: send_status returned 0x%x", __func__, err); goto out; } - status = ((status & MMC_R1_CURRENT_STATE_MASK) >> MMC_R1_CURRENT_STATE_POS); - if (status != MMC_R1_CURRENT_STATE_TRAN) { + + if (MMC_R1_CURRENT_STATE_STATUS(status) != MMC_R1_CURRENT_STATE_TRAN) { ESP_LOGE(TAG, "%s: card not in transfer state", __func__); err = ESP_ERR_INVALID_STATE; goto out; From 9c7609a0e789e6607d00656620ab5e7c6e7bd608 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20M=C3=BAdry?= Date: Tue, 15 Oct 2024 23:22:27 +0200 Subject: [PATCH 2/2] fix(sdmmc): Send status (CMD13) even if write/read command fails --- components/sdmmc/include/sd_protocol_defs.h | 2 +- components/sdmmc/sdmmc_cmd.c | 30 ++++++++++++++++----- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/components/sdmmc/include/sd_protocol_defs.h b/components/sdmmc/include/sd_protocol_defs.h index f3252be38fc..8eb52ca6b0a 100644 --- a/components/sdmmc/include/sd_protocol_defs.h +++ b/components/sdmmc/include/sd_protocol_defs.h @@ -108,7 +108,7 @@ extern "C" { #define MMC_R1_CURRENT_STATE_POS (9) #define MMC_R1_CURRENT_STATE_MASK (0x1E00)/* card current state */ #define MMC_R1_CURRENT_STATE_TRAN (4) -#define MMC_R1_CURRENT_STATE_STATUS(status) ((status & MMC_R1_CURRENT_STATE_MASK) >> MMC_R1_CURRENT_STATE_POS) +#define MMC_R1_CURRENT_STATE_STATUS(status) (((status) & MMC_R1_CURRENT_STATE_MASK) >> MMC_R1_CURRENT_STATE_POS) /* SPI mode R1 response type bits */ #define SD_SPI_R1_IDLE_STATE (1<<0) diff --git a/components/sdmmc/sdmmc_cmd.c b/components/sdmmc/sdmmc_cmd.c index 24acb6cb4a0..9d54ba3e1c2 100644 --- a/components/sdmmc/sdmmc_cmd.c +++ b/components/sdmmc/sdmmc_cmd.c @@ -444,7 +444,7 @@ esp_err_t sdmmc_write_sectors(sdmmc_card_t* card, const void* src, return err; } -static bool mmc_ready_for_data(uint32_t status) +static bool sdmmc_ready_for_data(uint32_t status) { return (status & MMC_R1_READY_FOR_DATA) && (MMC_R1_CURRENT_STATE_STATUS(status) == MMC_R1_CURRENT_STATE_TRAN); } @@ -474,18 +474,26 @@ esp_err_t sdmmc_write_sectors_dma(sdmmc_card_t* card, const void* src, } else { cmd.arg = start_block * block_size; } + + uint32_t status = 0; esp_err_t err = sdmmc_send_cmd(card, &cmd); + esp_err_t err_cmd13 = sdmmc_send_cmd_send_status(card, &status); + if (err != ESP_OK) { - ESP_LOGE(TAG, "%s: sdmmc_send_cmd returned 0x%x", __func__, err); + if (err_cmd13 == ESP_OK) { + ESP_LOGE(TAG, "%s: sdmmc_send_cmd returned 0x%x, status 0x%" PRIx32, __func__, err, status); + } else { + ESP_LOGE(TAG, "%s: sdmmc_send_cmd returned 0x%x, failed to get status (0x%x)", __func__, err, err_cmd13); + } return err; } - uint32_t status = 0; + size_t count = 0; int64_t yield_delay_us = 100 * 1000; // initially 100ms int64_t t0 = esp_timer_get_time(); int64_t t1 = 0; /* SD mode: wait for the card to become idle based on R1 status */ - while (!host_is_spi(card) && !mmc_ready_for_data(status)) { + while (!host_is_spi(card) && !sdmmc_ready_for_data(status)) { t1 = esp_timer_get_time(); if (t1 - t0 > SDMMC_READY_FOR_DATA_TIMEOUT_US) { ESP_LOGE(TAG, "write sectors dma - timeout"); @@ -596,18 +604,26 @@ esp_err_t sdmmc_read_sectors_dma(sdmmc_card_t* card, void* dst, } else { cmd.arg = start_block * block_size; } + + uint32_t status = 0; esp_err_t err = sdmmc_send_cmd(card, &cmd); + esp_err_t err_cmd13 = sdmmc_send_cmd_send_status(card, &status); + if (err != ESP_OK) { - ESP_LOGE(TAG, "%s: sdmmc_send_cmd returned 0x%x", __func__, err); + if (err_cmd13 == ESP_OK) { + ESP_LOGE(TAG, "%s: sdmmc_send_cmd returned 0x%x, status 0x%" PRIx32, __func__, err, status); + } else { + ESP_LOGE(TAG, "%s: sdmmc_send_cmd returned 0x%x, failed to get status (0x%x)", __func__, err, err_cmd13); + } return err; } - uint32_t status = 0; + size_t count = 0; int64_t yield_delay_us = 100 * 1000; // initially 100ms int64_t t0 = esp_timer_get_time(); int64_t t1 = 0; /* SD mode: wait for the card to become idle based on R1 status */ - while (!host_is_spi(card) && !mmc_ready_for_data(status)) { + while (!host_is_spi(card) && !sdmmc_ready_for_data(status)) { t1 = esp_timer_get_time(); if (t1 - t0 > SDMMC_READY_FOR_DATA_TIMEOUT_US) { ESP_LOGE(TAG, "read sectors dma - timeout");