forked from espressif/esp-idf
fix(sdmmc): Send ACMD22 if CMD25 fails
Send the number of the written write blocks (ACMD22) after write multiple blocks fails (CMD25)
This commit is contained in:
@@ -67,6 +67,7 @@ extern "C" {
|
|||||||
/* SD application commands */ /* response type */
|
/* SD application commands */ /* response type */
|
||||||
#define SD_APP_SET_BUS_WIDTH 6 /* R1 */
|
#define SD_APP_SET_BUS_WIDTH 6 /* R1 */
|
||||||
#define SD_APP_SD_STATUS 13 /* R2 */
|
#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_OP_COND 41 /* R3 */
|
||||||
#define SD_APP_SEND_SCR 51 /* R1 */
|
#define SD_APP_SEND_SCR 51 /* R1 */
|
||||||
|
|
||||||
@@ -247,6 +248,7 @@ extern "C" {
|
|||||||
#define MMC_CSD_CAPACITY(resp) ((MMC_CSD_C_SIZE((resp))+1) << \
|
#define MMC_CSD_CAPACITY(resp) ((MMC_CSD_C_SIZE((resp))+1) << \
|
||||||
(MMC_CSD_C_SIZE_MULT((resp))+2))
|
(MMC_CSD_C_SIZE_MULT((resp))+2))
|
||||||
#define MMC_CSD_C_SIZE_MULT(resp) MMC_RSP_BITS((resp), 47, 3)
|
#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) */
|
/* MMC v1 R2 response (CID) */
|
||||||
#define MMC_CID_MID_V1(resp) MMC_RSP_BITS((resp), 104, 24)
|
#define MMC_CID_MID_V1(resp) MMC_RSP_BITS((resp), 104, 24)
|
||||||
|
@@ -409,6 +409,32 @@ esp_err_t sdmmc_send_cmd_send_status(sdmmc_card_t* card, uint32_t* out_status)
|
|||||||
return ESP_OK;
|
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,
|
esp_err_t sdmmc_write_sectors(sdmmc_card_t* card, const void* src,
|
||||||
size_t start_block, size_t block_count)
|
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;
|
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,
|
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)
|
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);
|
esp_err_t err_cmd13 = sdmmc_send_cmd_send_status(card, &status);
|
||||||
|
|
||||||
if (err != ESP_OK) {
|
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) {
|
if (err_cmd13 == ESP_OK) {
|
||||||
ESP_LOGE(TAG, "%s: sdmmc_send_cmd returned 0x%x, status 0x%" PRIx32, __func__, err, status);
|
ESP_LOGE(TAG, "%s: sdmmc_send_cmd returned 0x%x, status 0x%" PRIx32, __func__, err, status);
|
||||||
} else {
|
} else {
|
||||||
|
@@ -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_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_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_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 */
|
/* Higher level functions */
|
||||||
esp_err_t sdmmc_enable_hs_mode(sdmmc_card_t* card);
|
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;
|
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);
|
void sdmmc_flip_byte_order(uint32_t* response, size_t size);
|
||||||
|
|
||||||
esp_err_t sdmmc_fix_host_flags(sdmmc_card_t* card);
|
esp_err_t sdmmc_fix_host_flags(sdmmc_card_t* card);
|
||||||
|
Reference in New Issue
Block a user