mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
sdmmc: incrementally increase delay of vTaskDelay
Prevents unnecessary slowdown in polling functions
This commit is contained in:
parent
ca2624e0eb
commit
f13c9f746f
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@ -79,12 +79,18 @@ esp_err_t sdmmc_host_reset(void)
|
|||||||
SDMMC.ctrl.fifo_reset = 1;
|
SDMMC.ctrl.fifo_reset = 1;
|
||||||
|
|
||||||
// Wait for the reset bits to be cleared by hardware
|
// Wait for the reset bits to be cleared by hardware
|
||||||
|
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;
|
||||||
while (SDMMC.ctrl.controller_reset || SDMMC.ctrl.fifo_reset || SDMMC.ctrl.dma_reset) {
|
while (SDMMC.ctrl.controller_reset || SDMMC.ctrl.fifo_reset || SDMMC.ctrl.dma_reset) {
|
||||||
if (esp_timer_get_time() - t0 > SDMMC_HOST_RESET_TIMEOUT_US) {
|
t1 = esp_timer_get_time();
|
||||||
|
if (t1 - t0 > SDMMC_HOST_RESET_TIMEOUT_US) {
|
||||||
return ESP_ERR_TIMEOUT;
|
return ESP_ERR_TIMEOUT;
|
||||||
}
|
}
|
||||||
vTaskDelay(1);
|
if (t1 - t0 > yield_delay_us) {
|
||||||
|
yield_delay_us *= 2;
|
||||||
|
vTaskDelay(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
@ -195,13 +201,14 @@ static esp_err_t sdmmc_host_clock_update_command(int slot)
|
|||||||
|
|
||||||
ESP_RETURN_ON_ERROR(sdmmc_host_start_command(slot, cmd_val, 0), TAG, "sdmmc_host_start_command returned 0x%x", err_rc_);
|
ESP_RETURN_ON_ERROR(sdmmc_host_start_command(slot, cmd_val, 0), TAG, "sdmmc_host_start_command returned 0x%x", err_rc_);
|
||||||
|
|
||||||
|
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;
|
||||||
while (true) {
|
while (true) {
|
||||||
|
t1 = esp_timer_get_time();
|
||||||
if (esp_timer_get_time() - t0 > SDMMC_HOST_CLOCK_UPDATE_CMD_TIMEOUT_US) {
|
if (t1 - t0 > SDMMC_HOST_CLOCK_UPDATE_CMD_TIMEOUT_US) {
|
||||||
return ESP_ERR_TIMEOUT;
|
return ESP_ERR_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sending clock update command to the CIU can generate HLE error.
|
// Sending clock update command to the CIU can generate HLE error.
|
||||||
// According to the manual, this is okay and we must retry the command.
|
// According to the manual, this is okay and we must retry the command.
|
||||||
if (SDMMC.rintsts.hle) {
|
if (SDMMC.rintsts.hle) {
|
||||||
@ -215,8 +222,10 @@ static esp_err_t sdmmc_host_clock_update_command(int slot)
|
|||||||
repeat = false;
|
repeat = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (t1 - t0 > yield_delay_us) {
|
||||||
vTaskDelay(1);
|
yield_delay_us *= 2;
|
||||||
|
vTaskDelay(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -401,12 +410,18 @@ esp_err_t sdmmc_host_start_command(int slot, sdmmc_hw_cmd_t cmd, uint32_t arg) {
|
|||||||
/* Outputs should be synchronized to cclk_out */
|
/* Outputs should be synchronized to cclk_out */
|
||||||
cmd.use_hold_reg = 1;
|
cmd.use_hold_reg = 1;
|
||||||
|
|
||||||
|
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;
|
||||||
while (SDMMC.cmd.start_command == 1) {
|
while (SDMMC.cmd.start_command == 1) {
|
||||||
if (esp_timer_get_time() - t0 > SDMMC_HOST_START_CMD_TIMEOUT_US) {
|
t1 = esp_timer_get_time();
|
||||||
|
if (t1 - t0 > SDMMC_HOST_START_CMD_TIMEOUT_US) {
|
||||||
return ESP_ERR_TIMEOUT;
|
return ESP_ERR_TIMEOUT;
|
||||||
}
|
}
|
||||||
vTaskDelay(1);
|
if (t1 - t0 > yield_delay_us) {
|
||||||
|
yield_delay_us *= 2;
|
||||||
|
vTaskDelay(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
SDMMC.cmdarg = arg;
|
SDMMC.cmdarg = arg;
|
||||||
cmd.card_num = slot;
|
cmd.card_num = slot;
|
||||||
@ -866,7 +881,7 @@ static void sdmmc_isr(void* arg) {
|
|||||||
|
|
||||||
uint32_t sdio_pending = SDMMC.mintsts.sdio;
|
uint32_t sdio_pending = SDMMC.mintsts.sdio;
|
||||||
if (sdio_pending) {
|
if (sdio_pending) {
|
||||||
// disable the interrupt (no need to clear here, this is done in sdmmc_host_io_wait_int)
|
// disable the interrupt (no need to clear here, this is done in sdmmc_host_io_int_wait)
|
||||||
SDMMC.intmask.sdio &= ~sdio_pending;
|
SDMMC.intmask.sdio &= ~sdio_pending;
|
||||||
xSemaphoreGiveFromISR(s_io_intr_event, &higher_priority_task_awoken);
|
xSemaphoreGiveFromISR(s_io_intr_event, &higher_priority_task_awoken);
|
||||||
}
|
}
|
||||||
|
@ -452,22 +452,28 @@ esp_err_t sdmmc_write_sectors_dma(sdmmc_card_t* card, const void* src,
|
|||||||
}
|
}
|
||||||
uint32_t status = 0;
|
uint32_t status = 0;
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
|
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;
|
||||||
/* 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) && !(status & MMC_R1_READY_FOR_DATA)) {
|
||||||
if (esp_timer_get_time() - t0 > SDMMC_READY_FOR_DATA_TIMEOUT_US) {
|
t1 = esp_timer_get_time();
|
||||||
|
if (t1 - t0 > SDMMC_READY_FOR_DATA_TIMEOUT_US) {
|
||||||
ESP_LOGE(TAG, "write sectors dma - timeout");
|
ESP_LOGE(TAG, "write sectors dma - timeout");
|
||||||
return ESP_ERR_TIMEOUT;
|
return ESP_ERR_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
if (t1 - t0 > yield_delay_us) {
|
||||||
|
yield_delay_us *= 2;
|
||||||
|
vTaskDelay(1);
|
||||||
|
}
|
||||||
err = sdmmc_send_cmd_send_status(card, &status);
|
err = sdmmc_send_cmd_send_status(card, &status);
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "%s: sdmmc_send_cmd_send_status returned 0x%x", __func__, err);
|
ESP_LOGE(TAG, "%s: sdmmc_send_cmd_send_status returned 0x%x", __func__, err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
if (++count % 10 == 0) {
|
if (++count % 16 == 0) {
|
||||||
ESP_LOGV(TAG, "waiting for card to become ready (%d)", count);
|
ESP_LOGV(TAG, "waiting for card to become ready (%d)", count);
|
||||||
}
|
}
|
||||||
vTaskDelay(1);
|
|
||||||
}
|
}
|
||||||
/* SPI mode: although card busy indication is based on the busy token,
|
/* 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
|
* SD spec recommends that the host checks the results of programming by sending
|
||||||
@ -559,21 +565,28 @@ esp_err_t sdmmc_read_sectors_dma(sdmmc_card_t* card, void* dst,
|
|||||||
}
|
}
|
||||||
uint32_t status = 0;
|
uint32_t status = 0;
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
|
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;
|
||||||
|
/* 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) && !(status & MMC_R1_READY_FOR_DATA)) {
|
||||||
if (esp_timer_get_time() - t0 > SDMMC_READY_FOR_DATA_TIMEOUT_US) {
|
t1 = esp_timer_get_time();
|
||||||
|
if (t1 - t0 > SDMMC_READY_FOR_DATA_TIMEOUT_US) {
|
||||||
ESP_LOGE(TAG, "read sectors dma - timeout");
|
ESP_LOGE(TAG, "read sectors dma - timeout");
|
||||||
return ESP_ERR_TIMEOUT;
|
return ESP_ERR_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
if (t1 - t0 > yield_delay_us) {
|
||||||
|
yield_delay_us *= 2;
|
||||||
|
vTaskDelay(1);
|
||||||
|
}
|
||||||
err = sdmmc_send_cmd_send_status(card, &status);
|
err = sdmmc_send_cmd_send_status(card, &status);
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "%s: sdmmc_send_cmd_send_status returned 0x%x", __func__, err);
|
ESP_LOGE(TAG, "%s: sdmmc_send_cmd_send_status returned 0x%x", __func__, err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
if (++count % 10 == 0) {
|
if (++count % 16 == 0) {
|
||||||
ESP_LOGV(TAG, "waiting for card to become ready (%d)", count);
|
ESP_LOGV(TAG, "waiting for card to become ready (%d)", count);
|
||||||
}
|
}
|
||||||
vTaskDelay(1);
|
|
||||||
}
|
}
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
@ -30,8 +30,8 @@
|
|||||||
#define SDMMC_GO_IDLE_DELAY_MS 20
|
#define SDMMC_GO_IDLE_DELAY_MS 20
|
||||||
#define SDMMC_IO_SEND_OP_COND_DELAY_MS 10
|
#define SDMMC_IO_SEND_OP_COND_DELAY_MS 10
|
||||||
|
|
||||||
#define SDMMC_INIT_WAIT_DATA_READY_TIMEOUT_US 5000 * 1000
|
#define SDMMC_INIT_WAIT_DATA_READY_TIMEOUT_US (5000 * 1000)
|
||||||
#define SDMMC_READY_FOR_DATA_TIMEOUT_US 5000 * 1000
|
#define SDMMC_READY_FOR_DATA_TIMEOUT_US (5000 * 1000)
|
||||||
|
|
||||||
/* These delay values are mostly useful for cases when CD pin is not used, and
|
/* These delay values are mostly useful for cases when CD pin is not used, and
|
||||||
* the card is removed. In this case, SDMMC peripheral may not always return
|
* the card is removed. In this case, SDMMC peripheral may not always return
|
||||||
|
@ -139,12 +139,19 @@ esp_err_t sdmmc_init_sd_wait_data_ready(sdmmc_card_t* card)
|
|||||||
/* Wait for the card to be ready for data transfers */
|
/* Wait for the card to be ready for data transfers */
|
||||||
uint32_t status = 0;
|
uint32_t status = 0;
|
||||||
uint32_t count = 0;
|
uint32_t count = 0;
|
||||||
|
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;
|
||||||
while (!host_is_spi(card) && !(status & MMC_R1_READY_FOR_DATA)) {
|
while (!host_is_spi(card) && !(status & MMC_R1_READY_FOR_DATA)) {
|
||||||
if (esp_timer_get_time() - t0 > SDMMC_INIT_WAIT_DATA_READY_TIMEOUT_US) {
|
t1 = esp_timer_get_time();
|
||||||
|
if (t1 - t0 > SDMMC_INIT_WAIT_DATA_READY_TIMEOUT_US) {
|
||||||
ESP_LOGE(TAG, "init wait data ready - timeout");
|
ESP_LOGE(TAG, "init wait data ready - timeout");
|
||||||
return ESP_ERR_TIMEOUT;
|
return ESP_ERR_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
if (t1 - t0 > yield_delay_us) {
|
||||||
|
yield_delay_us *= 2;
|
||||||
|
vTaskDelay(1);
|
||||||
|
}
|
||||||
esp_err_t err = sdmmc_send_cmd_send_status(card, &status);
|
esp_err_t err = sdmmc_send_cmd_send_status(card, &status);
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
return err;
|
return err;
|
||||||
@ -152,7 +159,6 @@ esp_err_t sdmmc_init_sd_wait_data_ready(sdmmc_card_t* card)
|
|||||||
if (++count % 16 == 0) {
|
if (++count % 16 == 0) {
|
||||||
ESP_LOGV(TAG, "waiting for card to become ready (%d)", count);
|
ESP_LOGV(TAG, "waiting for card to become ready (%d)", count);
|
||||||
}
|
}
|
||||||
vTaskDelay(1);
|
|
||||||
}
|
}
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user