mirror of
https://github.com/espressif/esp-idf.git
synced 2025-07-30 10:47:19 +02:00
fix(sdmmc): Generalize waiting for card idle to a function
This commit is contained in:
@ -5,7 +5,6 @@
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "esp_timer.h"
|
||||
#include "sdmmc_common.h"
|
||||
|
||||
static const char* TAG = "sdmmc_cmd";
|
||||
@ -517,8 +516,10 @@ esp_err_t sdmmc_write_sectors_dma(sdmmc_card_t* card, const void* src,
|
||||
|
||||
if (err != ESP_OK) {
|
||||
if (cmd.opcode == MMC_WRITE_BLOCK_MULTIPLE) {
|
||||
if (!sdmmc_ready_for_data(status)) {
|
||||
vTaskDelay(1);
|
||||
if (!host_is_spi(card)) {
|
||||
sdmmc_wait_for_idle(card, status); // wait for the card to be idle (in transfer state)
|
||||
} else {
|
||||
vTaskDelay(1); // when the host is in spi mode
|
||||
}
|
||||
size_t successfully_written_blocks = 0;
|
||||
if (sdmmc_send_cmd_num_of_written_blocks(card, &successfully_written_blocks) == ESP_OK) {
|
||||
@ -535,30 +536,19 @@ esp_err_t sdmmc_write_sectors_dma(sdmmc_card_t* card, const void* src,
|
||||
return err;
|
||||
}
|
||||
|
||||
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) && !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");
|
||||
if (!host_is_spi(card)) {
|
||||
switch (sdmmc_wait_for_idle(card, status)) {
|
||||
case ESP_OK:
|
||||
break;
|
||||
case ESP_ERR_TIMEOUT:
|
||||
ESP_LOGE(TAG, "%s: sdmmc_wait_for_idle timeout", __func__);
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
if (t1 - t0 > yield_delay_us) {
|
||||
yield_delay_us *= 2;
|
||||
vTaskDelay(1);
|
||||
}
|
||||
err = sdmmc_send_cmd_send_status(card, &status);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: sdmmc_send_cmd_send_status returned 0x%x", __func__, err);
|
||||
default:
|
||||
return err;
|
||||
}
|
||||
if (++count % 16 == 0) {
|
||||
ESP_LOGV(TAG, "waiting for card to become ready (%" PRIu32 ")", (uint32_t) count);
|
||||
}
|
||||
}
|
||||
|
||||
/* SPI mode: although card busy indication is based on the busy token,
|
||||
* SD spec recommends that the host checks the results of programming by sending
|
||||
* SEND_STATUS command. Some of the conditions reported in SEND_STATUS are not
|
||||
@ -665,29 +655,17 @@ esp_err_t sdmmc_read_sectors_dma(sdmmc_card_t* card, void* dst,
|
||||
return err;
|
||||
}
|
||||
|
||||
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) && !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");
|
||||
if (!host_is_spi(card)) {
|
||||
switch (sdmmc_wait_for_idle(card, status)) {
|
||||
case ESP_OK:
|
||||
break;
|
||||
case ESP_ERR_TIMEOUT:
|
||||
ESP_LOGE(TAG, "%s: sdmmc_wait_for_idle timeout", __func__);
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
if (t1 - t0 > yield_delay_us) {
|
||||
yield_delay_us *= 2;
|
||||
vTaskDelay(1);
|
||||
}
|
||||
err = sdmmc_send_cmd_send_status(card, &status);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: sdmmc_send_cmd_send_status returned 0x%x", __func__, err);
|
||||
default:
|
||||
return err;
|
||||
}
|
||||
if (++count % 16 == 0) {
|
||||
ESP_LOGV(TAG, "waiting for card to become ready (%d)", count);
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
@ -16,6 +16,8 @@
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "esp_log.h"
|
||||
#include "esp_timer.h"
|
||||
#include "sdmmc_common.h"
|
||||
|
||||
static const char* TAG = "sdmmc_common";
|
||||
@ -415,3 +417,33 @@ uint32_t sdmmc_get_erase_timeout_ms(const sdmmc_card_t* card, int arg, size_t er
|
||||
return sdmmc_sd_get_erase_timeout_ms(card, arg, erase_size_kb);
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t sdmmc_wait_for_idle(sdmmc_card_t* card, uint32_t status)
|
||||
{
|
||||
assert(!host_is_spi(card));
|
||||
esp_err_t err = ESP_OK;
|
||||
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 (!sdmmc_ready_for_data(status)) {
|
||||
t1 = esp_timer_get_time();
|
||||
if (t1 - t0 > SDMMC_READY_FOR_DATA_TIMEOUT_US) {
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
if (t1 - t0 > yield_delay_us) {
|
||||
yield_delay_us *= 2;
|
||||
vTaskDelay(1);
|
||||
}
|
||||
err = sdmmc_send_cmd_send_status(card, &status);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: sdmmc_send_cmd_send_status returned 0x%x", __func__, err);
|
||||
return err;
|
||||
}
|
||||
if (++count % 16 == 0) {
|
||||
ESP_LOGV(TAG, "waiting for card to become ready (%" PRIu32 ")", (uint32_t) count);
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
@ -30,6 +30,10 @@
|
||||
#include "soc/soc_caps.h"
|
||||
#include "esp_dma_utils.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define SDMMC_GO_IDLE_DELAY_MS 20
|
||||
#define SDMMC_IO_SEND_OP_COND_DELAY_MS 10
|
||||
|
||||
@ -176,6 +180,13 @@ void sdmmc_flip_byte_order(uint32_t* response, size_t size);
|
||||
|
||||
esp_err_t sdmmc_fix_host_flags(sdmmc_card_t* card);
|
||||
|
||||
// Use only with SDMMC mode (not SDSPI)
|
||||
esp_err_t sdmmc_wait_for_idle(sdmmc_card_t* card, uint32_t status);
|
||||
|
||||
//Currently only SDIO support using this buffer. And only 512 block size is supported.
|
||||
#define SDMMC_IO_BLOCK_SIZE 512
|
||||
esp_err_t sdmmc_allocate_aligned_buf(sdmmc_card_t* card);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user