forked from espressif/esp-idf
Merge branch 'fix/sdmmc_write_sectors_dma_always_send_cmd13' into 'master'
fix(sdmmc): sdmmc_write_sectors_dma always check card status after write Closes IDF-9632 See merge request espressif/esp-idf!34132
This commit is contained in:
@@ -108,6 +108,7 @@ extern "C" {
|
|||||||
#define MMC_R1_CURRENT_STATE_POS (9)
|
#define MMC_R1_CURRENT_STATE_POS (9)
|
||||||
#define MMC_R1_CURRENT_STATE_MASK (0x1E00)/* card current state */
|
#define MMC_R1_CURRENT_STATE_MASK (0x1E00)/* card current state */
|
||||||
#define MMC_R1_CURRENT_STATE_TRAN (4)
|
#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 */
|
/* SPI mode R1 response type bits */
|
||||||
#define SD_SPI_R1_IDLE_STATE (1<<0)
|
#define SD_SPI_R1_IDLE_STATE (1<<0)
|
||||||
@@ -424,7 +425,7 @@ extern "C" {
|
|||||||
*
|
*
|
||||||
* 67 45 23 01 ef cd ab 89
|
* 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=4 -> result=0x00000007
|
||||||
* start=0 len=12 -> result=0x00000567
|
* start=0 len=12 -> result=0x00000567
|
||||||
|
@@ -459,6 +459,11 @@ 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)
|
||||||
{
|
{
|
||||||
@@ -484,18 +489,26 @@ esp_err_t sdmmc_write_sectors_dma(sdmmc_card_t* card, const void* src,
|
|||||||
} else {
|
} else {
|
||||||
cmd.arg = start_block * block_size;
|
cmd.arg = start_block * block_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t status = 0;
|
||||||
esp_err_t err = sdmmc_send_cmd(card, &cmd);
|
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) {
|
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;
|
return err;
|
||||||
}
|
}
|
||||||
uint32_t status = 0;
|
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
int64_t yield_delay_us = 100 * 1000; // initially 100ms
|
int64_t yield_delay_us = 100 * 1000; // initially 100ms
|
||||||
int64_t t0 = esp_timer_get_time();
|
int64_t t0 = esp_timer_get_time();
|
||||||
int64_t t1 = 0;
|
int64_t t1 = 0;
|
||||||
/* SD mode: wait for the card to become idle based on R1 status */
|
/* 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) && !sdmmc_ready_for_data(status)) {
|
||||||
t1 = esp_timer_get_time();
|
t1 = esp_timer_get_time();
|
||||||
if (t1 - t0 > SDMMC_READY_FOR_DATA_TIMEOUT_US) {
|
if (t1 - t0 > SDMMC_READY_FOR_DATA_TIMEOUT_US) {
|
||||||
ESP_LOGE(TAG, "write sectors dma - timeout");
|
ESP_LOGE(TAG, "write sectors dma - timeout");
|
||||||
@@ -606,18 +619,26 @@ esp_err_t sdmmc_read_sectors_dma(sdmmc_card_t* card, void* dst,
|
|||||||
} else {
|
} else {
|
||||||
cmd.arg = start_block * block_size;
|
cmd.arg = start_block * block_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t status = 0;
|
||||||
esp_err_t err = sdmmc_send_cmd(card, &cmd);
|
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) {
|
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;
|
return err;
|
||||||
}
|
}
|
||||||
uint32_t status = 0;
|
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
int64_t yield_delay_us = 100 * 1000; // initially 100ms
|
int64_t yield_delay_us = 100 * 1000; // initially 100ms
|
||||||
int64_t t0 = esp_timer_get_time();
|
int64_t t0 = esp_timer_get_time();
|
||||||
int64_t t1 = 0;
|
int64_t t1 = 0;
|
||||||
/* SD mode: wait for the card to become idle based on R1 status */
|
/* 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) && !sdmmc_ready_for_data(status)) {
|
||||||
t1 = esp_timer_get_time();
|
t1 = esp_timer_get_time();
|
||||||
if (t1 - t0 > SDMMC_READY_FOR_DATA_TIMEOUT_US) {
|
if (t1 - t0 > SDMMC_READY_FOR_DATA_TIMEOUT_US) {
|
||||||
ESP_LOGE(TAG, "read sectors dma - timeout");
|
ESP_LOGE(TAG, "read sectors dma - timeout");
|
||||||
|
@@ -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);
|
ESP_LOGE(TAG, "%s: send_status returned 0x%x", __func__, err);
|
||||||
goto out;
|
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__);
|
ESP_LOGE(TAG, "%s: card not in transfer state", __func__);
|
||||||
err = ESP_ERR_INVALID_STATE;
|
err = ESP_ERR_INVALID_STATE;
|
||||||
goto out;
|
goto out;
|
||||||
|
Reference in New Issue
Block a user