[SDMMC] add reasonable timeouts to all while loops

Closes: https://github.com/espressif/esp-idf/pull/10532
pull/11218/head
Chip Weinberger 2023-01-18 15:22:07 -08:00 zatwierdzone przez BOT
rodzic a2aa9e3bef
commit 74d6215b7f
9 zmienionych plików z 41 dodań i 14 usunięć

Wyświetl plik

@ -9,6 +9,7 @@
#include <sys/param.h>
#include "esp_log.h"
#include "esp_intr_alloc.h"
#include "esp_timer.h"
#include "soc/soc_caps.h"
#include "soc/soc_pins.h"
#include "soc/gpio_periph.h"
@ -25,9 +26,6 @@
#define SDMMC_EVENT_QUEUE_LENGTH 32
#define SDMMC_TIMEOUT_MS 1000
static void sdmmc_isr(void* arg);
static void sdmmc_host_dma_init(void);
@ -78,9 +76,9 @@ esp_err_t sdmmc_host_reset(void)
SDMMC.ctrl.fifo_reset = 1;
// Wait for the reset bits to be cleared by hardware
int t0 = esp_timer_get_time();
int64_t t0 = esp_timer_get_time();
while (SDMMC.ctrl.controller_reset || SDMMC.ctrl.fifo_reset || SDMMC.ctrl.dma_reset) {
if (esp_timer_get_time() - t0 > SDMMC_TIMEOUT_MS) {
if (esp_timer_get_time() - t0 > SDMMC_HOST_RESET_TIMEOUT_US) {
return ESP_ERR_TIMEOUT;
}
}
@ -167,10 +165,10 @@ static esp_err_t sdmmc_host_clock_update_command(int slot)
return err;
}
int t0 = esp_timer_get_time();
int64_t t0 = esp_timer_get_time();
while (true) {
if (esp_timer_get_time() - t0 > SDMMC_TIMEOUT_MS) {
if (esp_timer_get_time() - t0 > SDMMC_HOST_CLOCK_UPDATE_CMD_TIMEOUT_US) {
return ESP_ERR_TIMEOUT;
}
@ -316,9 +314,9 @@ esp_err_t sdmmc_host_start_command(int slot, sdmmc_hw_cmd_t cmd, uint32_t arg) {
if (cmd.data_expected && cmd.rw && (SDMMC.wrtprt.cards & BIT(slot)) != 0) {
return ESP_ERR_INVALID_STATE;
}
int t0 = esp_timer_get_time();
int64_t t0 = esp_timer_get_time();
while (SDMMC.cmd.start_command == 1) {
if (esp_timer_get_time() - t0 > SDMMC_TIMEOUT_MS) {
if (esp_timer_get_time() - t0 > SDMMC_HOST_START_CMD_TIMEOUT_US) {
return ESP_ERR_TIMEOUT;
}
}

Wyświetl plik

@ -18,6 +18,10 @@ typedef struct {
uint32_t dma_status; ///< masked DMA interrupt status
} sdmmc_event_t;
#define SDMMC_HOST_CLOCK_UPDATE_CMD_TIMEOUT_US 1000 * 1000
#define SDMMC_HOST_START_CMD_TIMEOUT_US 1000 * 1000
#define SDMMC_HOST_RESET_TIMEOUT_US 5000 * 1000
esp_err_t sdmmc_host_reset(void);
esp_err_t sdmmc_host_start_command(int slot, sdmmc_hw_cmd_t cmd, uint32_t arg);

Wyświetl plik

@ -17,6 +17,7 @@
#include "driver/sdmmc_types.h"
#include "driver/sdmmc_defs.h"
#include "driver/sdmmc_host.h"
#include "esp_timer.h"
#include "sdmmc_private.h"

Wyświetl plik

@ -88,7 +88,6 @@ static esp_err_t mount_prepare_mem(const char *base_path,
if (ff_diskio_get_drive(&pdrv) != ESP_OK || pdrv == FF_DRV_NOT_USED) {
ESP_LOGD(TAG, "the maximum count of volumes is already mounted");
return ESP_ERR_NO_MEM;
}
// not using ff_memalloc here, as allocation in internal RAM is preferred

Wyświetl plik

@ -6,6 +6,6 @@ idf_component_register(SRCS "sdmmc_cmd.c"
"sdmmc_sd.c"
INCLUDE_DIRS include
REQUIRES driver
PRIV_REQUIRES soc)
PRIV_REQUIRES soc esp_timer)
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")

Wyświetl plik

@ -3,6 +3,7 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "esp_timer.h"
#include "sdmmc_common.h"
@ -451,11 +452,16 @@ esp_err_t sdmmc_write_sectors_dma(sdmmc_card_t* card, const void* src,
}
uint32_t status = 0;
size_t count = 0;
int64_t t0 = esp_timer_get_time();
/* SD mode: wait for the card to become idle based on R1 status */
while (!host_is_spi(card) && !(status & MMC_R1_READY_FOR_DATA)) {
// TODO: add some timeout here
if (esp_timer_get_time() - t0 > SDMMC_READY_FOR_DATA_TIMEOUT_US) {
ESP_LOGE(TAG, "write sectors dma - timeout");
return ESP_ERR_TIMEOUT;
}
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 % 10 == 0) {
@ -470,6 +476,7 @@ esp_err_t sdmmc_write_sectors_dma(sdmmc_card_t* card, const void* src,
if (host_is_spi(card)) {
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 (status & SD_SPI_R2_CARD_LOCKED) {
@ -551,10 +558,15 @@ esp_err_t sdmmc_read_sectors_dma(sdmmc_card_t* card, void* dst,
}
uint32_t status = 0;
size_t count = 0;
int64_t t0 = esp_timer_get_time();
while (!host_is_spi(card) && !(status & MMC_R1_READY_FOR_DATA)) {
// TODO: add some timeout here
if (esp_timer_get_time() - t0 > SDMMC_READY_FOR_DATA_TIMEOUT_US) {
ESP_LOGE(TAG, "read sectors dma - timeout");
return ESP_ERR_TIMEOUT;
}
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 % 10 == 0) {
@ -644,6 +656,7 @@ esp_err_t sdmmc_erase_sectors(sdmmc_card_t* card, size_t start_sector,
uint32_t status;
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 (status != 0) {

Wyświetl plik

@ -30,6 +30,9 @@
#define SDMMC_GO_IDLE_DELAY_MS 20
#define SDMMC_IO_SEND_OP_COND_DELAY_MS 10
#define SDMMC_INIT_WAIT_DATA_READY_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
* the card is removed. In this case, SDMMC peripheral may not always return
* CMD_DONE / DATA_DONE interrupts after signaling the error. These timeouts work

Wyświetl plik

@ -321,6 +321,8 @@ esp_err_t sdmmc_io_read_bytes(sdmmc_card_t* card, uint32_t function,
size_t size_aligned = size & (~3);
size_t will_transfer = size_aligned > 0 ? size_aligned : size;
// Note: sdmmc_io_rw_extended has an internal timeout,
// typically SDMMC_DEFAULT_CMD_TIMEOUT_MS
esp_err_t err = sdmmc_io_rw_extended(card, function, addr,
SD_ARG_CMD53_READ | SD_ARG_CMD53_INCREMENT,
pc_dst, will_transfer);
@ -344,6 +346,8 @@ esp_err_t sdmmc_io_write_bytes(sdmmc_card_t* card, uint32_t function,
size_t size_aligned = size & (~3);
size_t will_transfer = size_aligned > 0 ? size_aligned : size;
// Note: sdmmc_io_rw_extended has an internal timeout,
// typically SDMMC_DEFAULT_CMD_TIMEOUT_MS
esp_err_t err = sdmmc_io_rw_extended(card, function, addr,
SD_ARG_CMD53_WRITE | SD_ARG_CMD53_INCREMENT,
(void*) pc_src, will_transfer);

Wyświetl plik

@ -14,6 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "esp_timer.h"
#include "sdmmc_common.h"
@ -138,8 +139,12 @@ esp_err_t sdmmc_init_sd_wait_data_ready(sdmmc_card_t* card)
/* Wait for the card to be ready for data transfers */
uint32_t status = 0;
uint32_t count = 0;
int64_t t0 = esp_timer_get_time();
while (!host_is_spi(card) && !(status & MMC_R1_READY_FOR_DATA)) {
// TODO: add some timeout here
if (esp_timer_get_time() - t0 > SDMMC_INIT_WAIT_DATA_READY_TIMEOUT_US) {
ESP_LOGE(TAG, "init wait data ready - timeout");
return ESP_ERR_TIMEOUT;
}
esp_err_t err = sdmmc_send_cmd_send_status(card, &status);
if (err != ESP_OK) {
return err;