diff --git a/components/sdmmc/include/sd_protocol_defs.h b/components/sdmmc/include/sd_protocol_defs.h index 8eb52ca6b0..02b18cfcce 100644 --- a/components/sdmmc/include/sd_protocol_defs.h +++ b/components/sdmmc/include/sd_protocol_defs.h @@ -67,6 +67,7 @@ extern "C" { /* SD application commands */ /* response type */ #define SD_APP_SET_BUS_WIDTH 6 /* R1 */ #define SD_APP_SD_STATUS 13 /* R2 */ +#define SD_APP_SEND_NUM_WR_BLOCKS 22 /* R1 */ #define SD_APP_OP_COND 41 /* R3 */ #define SD_APP_SEND_SCR 51 /* R1 */ @@ -247,6 +248,7 @@ extern "C" { #define MMC_CSD_CAPACITY(resp) ((MMC_CSD_C_SIZE((resp))+1) << \ (MMC_CSD_C_SIZE_MULT((resp))+2)) #define MMC_CSD_C_SIZE_MULT(resp) MMC_RSP_BITS((resp), 47, 3) +#define MMC_CSD_WRITE_BL_PARTIAL(resp) MMC_RSP_BITS((resp), 21, 1) /* MMC v1 R2 response (CID) */ #define MMC_CID_MID_V1(resp) MMC_RSP_BITS((resp), 104, 24) diff --git a/components/sdmmc/sdmmc_cmd.c b/components/sdmmc/sdmmc_cmd.c index a281323ce6..9be0179148 100644 --- a/components/sdmmc/sdmmc_cmd.c +++ b/components/sdmmc/sdmmc_cmd.c @@ -409,6 +409,32 @@ esp_err_t sdmmc_send_cmd_send_status(sdmmc_card_t* card, uint32_t* out_status) return ESP_OK; } +esp_err_t sdmmc_send_cmd_num_of_written_blocks(sdmmc_card_t* card, size_t* out_num_blocks) +{ + esp_err_t err = ESP_OK; + uint32_t buf = 0; + sdmmc_command_t cmd = { + .data = &buf, + .datalen = sizeof(buf), + .buflen = sizeof(buf), + .blklen = sizeof(buf), + .flags = SCF_CMD_ADTC | SCF_RSP_R1 | SCF_CMD_READ, + .opcode = SD_APP_SEND_NUM_WR_BLOCKS + }; + + err = sdmmc_send_app_cmd(card, &cmd); + if (err != ESP_OK) { + ESP_LOGE(TAG, "%s: sdmmc_send_app_cmd returned 0x%x, failed to get number of written write blocks", __func__, err); + return err; + } + + size_t result = __builtin_bswap32(buf); + if (out_num_blocks) { + *out_num_blocks = result; + } + return err; +} + esp_err_t sdmmc_write_sectors(sdmmc_card_t* card, const void* src, size_t start_block, size_t block_count) { @@ -459,11 +485,6 @@ esp_err_t sdmmc_write_sectors(sdmmc_card_t* card, const void* src, return err; } -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); -} - 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) { @@ -495,6 +516,17 @@ esp_err_t sdmmc_write_sectors_dma(sdmmc_card_t* card, const void* src, esp_err_t err_cmd13 = sdmmc_send_cmd_send_status(card, &status); if (err != ESP_OK) { + if (cmd.opcode == MMC_WRITE_BLOCK_MULTIPLE) { + if (!sdmmc_ready_for_data(status)) { + vTaskDelay(1); + } + size_t successfully_written_blocks = 0; + if (sdmmc_send_cmd_num_of_written_blocks(card, &successfully_written_blocks) == ESP_OK) { + ESP_LOGD(TAG, "%s: successfully wrote %zu blocks out of %zu", __func__, successfully_written_blocks, block_count); + } else { + ESP_LOGE(TAG, "%s: sdmmc_send_cmd_num_of_written_blocks 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 { diff --git a/components/sdmmc/sdmmc_common.h b/components/sdmmc/sdmmc_common.h index 2753d3d681..a33d2d641c 100644 --- a/components/sdmmc/sdmmc_common.h +++ b/components/sdmmc/sdmmc_common.h @@ -77,6 +77,7 @@ esp_err_t sdmmc_send_cmd_send_scr(sdmmc_card_t* card, sdmmc_scr_t *out_scr); esp_err_t sdmmc_send_cmd_set_bus_width(sdmmc_card_t* card, int width); esp_err_t sdmmc_send_cmd_send_status(sdmmc_card_t* card, uint32_t* out_status); esp_err_t sdmmc_send_cmd_crc_on_off(sdmmc_card_t* card, bool crc_enable); +esp_err_t sdmmc_send_cmd_num_of_written_blocks(sdmmc_card_t* card, size_t* out_num_blocks); /* Higher level functions */ esp_err_t sdmmc_enable_hs_mode(sdmmc_card_t* card); @@ -154,6 +155,11 @@ static inline uint32_t get_host_ocr(float voltage) return SD_OCR_VOL_MASK; } +static inline 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); +} + void sdmmc_flip_byte_order(uint32_t* response, size_t size); esp_err_t sdmmc_fix_host_flags(sdmmc_card_t* card);