forked from espressif/esp-idf
Merge branch 'bugfix/sd_card_fixes' into 'master'
SD card fixes See merge request !1393
This commit is contained in:
@@ -102,6 +102,7 @@ typedef struct {
|
|||||||
#define SCF_RSP_R6 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX)
|
#define SCF_RSP_R6 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX)
|
||||||
#define SCF_RSP_R7 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX)
|
#define SCF_RSP_R7 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX)
|
||||||
esp_err_t error; /*!< error returned from transfer */
|
esp_err_t error; /*!< error returned from transfer */
|
||||||
|
int timeout_ms; /*!< response timeout, in milliseconds */
|
||||||
} sdmmc_command_t;
|
} sdmmc_command_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -127,6 +128,7 @@ typedef struct {
|
|||||||
esp_err_t (*set_card_clk)(int slot, uint32_t freq_khz); /*!< host function to set card clock frequency */
|
esp_err_t (*set_card_clk)(int slot, uint32_t freq_khz); /*!< host function to set card clock frequency */
|
||||||
esp_err_t (*do_transaction)(int slot, sdmmc_command_t* cmdinfo); /*!< host function to do a transaction */
|
esp_err_t (*do_transaction)(int slot, sdmmc_command_t* cmdinfo); /*!< host function to do a transaction */
|
||||||
esp_err_t (*deinit)(void); /*!< host function to deinitialize the driver */
|
esp_err_t (*deinit)(void); /*!< host function to deinitialize the driver */
|
||||||
|
int command_timeout_ms; /*!< timeout, in milliseconds, of a single command. Set to 0 to use the default value. */
|
||||||
} sdmmc_host_t;
|
} sdmmc_host_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -33,13 +33,6 @@
|
|||||||
*/
|
*/
|
||||||
#define SDMMC_DMA_DESC_CNT 4
|
#define SDMMC_DMA_DESC_CNT 4
|
||||||
|
|
||||||
/* Max delay value is 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. This delay works
|
|
||||||
* as a safety net in such cases.
|
|
||||||
*/
|
|
||||||
#define SDMMC_MAX_EVT_WAIT_DELAY_MS 1000
|
|
||||||
|
|
||||||
static const char* TAG = "sdmmc_req";
|
static const char* TAG = "sdmmc_req";
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -206,7 +199,7 @@ static esp_err_t handle_idle_state_events()
|
|||||||
static esp_err_t handle_event(sdmmc_command_t* cmd, sdmmc_req_state_t* state)
|
static esp_err_t handle_event(sdmmc_command_t* cmd, sdmmc_req_state_t* state)
|
||||||
{
|
{
|
||||||
sdmmc_event_t evt;
|
sdmmc_event_t evt;
|
||||||
esp_err_t err = sdmmc_host_wait_for_event(SDMMC_MAX_EVT_WAIT_DELAY_MS / portTICK_PERIOD_MS, &evt);
|
esp_err_t err = sdmmc_host_wait_for_event(cmd->timeout_ms / portTICK_PERIOD_MS, &evt);
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "sdmmc_host_wait_for_event returned 0x%x", err);
|
ESP_LOGE(TAG, "sdmmc_host_wait_for_event returned 0x%x", err);
|
||||||
if (err == ESP_ERR_TIMEOUT) {
|
if (err == ESP_ERR_TIMEOUT) {
|
||||||
|
@@ -28,6 +28,14 @@
|
|||||||
|
|
||||||
#define SDMMC_GO_IDLE_DELAY_MS 20
|
#define SDMMC_GO_IDLE_DELAY_MS 20
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
* as a safety net in such cases.
|
||||||
|
*/
|
||||||
|
#define SDMMC_DEFAULT_CMD_TIMEOUT_MS 1000 // Max timeout of ordinary commands
|
||||||
|
#define SDMMC_WRITE_CMD_TIMEOUT_MS 5000 // Max timeout of write commands
|
||||||
|
|
||||||
static const char* TAG = "sdmmc_cmd";
|
static const char* TAG = "sdmmc_cmd";
|
||||||
|
|
||||||
static esp_err_t sdmmc_send_cmd(sdmmc_card_t* card, sdmmc_command_t* cmd);
|
static esp_err_t sdmmc_send_cmd(sdmmc_card_t* card, sdmmc_command_t* cmd);
|
||||||
@@ -344,9 +352,15 @@ void sdmmc_card_print_info(FILE* stream, const sdmmc_card_t* card)
|
|||||||
|
|
||||||
static esp_err_t sdmmc_send_cmd(sdmmc_card_t* card, sdmmc_command_t* cmd)
|
static esp_err_t sdmmc_send_cmd(sdmmc_card_t* card, sdmmc_command_t* cmd)
|
||||||
{
|
{
|
||||||
|
if (card->host.command_timeout_ms != 0) {
|
||||||
|
cmd->timeout_ms = card->host.command_timeout_ms;
|
||||||
|
} else if (cmd->timeout_ms == 0) {
|
||||||
|
cmd->timeout_ms = SDMMC_DEFAULT_CMD_TIMEOUT_MS;
|
||||||
|
}
|
||||||
|
|
||||||
int slot = card->host.slot;
|
int slot = card->host.slot;
|
||||||
ESP_LOGV(TAG, "sending cmd slot=%d op=%d arg=%x flags=%x data=%p blklen=%d datalen=%d",
|
ESP_LOGV(TAG, "sending cmd slot=%d op=%d arg=%x flags=%x data=%p blklen=%d datalen=%d timeout=%d",
|
||||||
slot, cmd->opcode, cmd->arg, cmd->flags, cmd->data, cmd->blklen, cmd->datalen);
|
slot, cmd->opcode, cmd->arg, cmd->flags, cmd->data, cmd->blklen, cmd->datalen, cmd->timeout_ms);
|
||||||
esp_err_t err = (*card->host.do_transaction)(slot, cmd);
|
esp_err_t err = (*card->host.do_transaction)(slot, cmd);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
ESP_LOGD(TAG, "sdmmc_req_run returned 0x%x", err);
|
ESP_LOGD(TAG, "sdmmc_req_run returned 0x%x", err);
|
||||||
@@ -758,7 +772,8 @@ static esp_err_t sdmmc_write_sectors_dma(sdmmc_card_t* card, const void* src,
|
|||||||
.flags = SCF_CMD_ADTC | SCF_RSP_R1,
|
.flags = SCF_CMD_ADTC | SCF_RSP_R1,
|
||||||
.blklen = block_size,
|
.blklen = block_size,
|
||||||
.data = (void*) src,
|
.data = (void*) src,
|
||||||
.datalen = block_count * block_size
|
.datalen = block_count * block_size,
|
||||||
|
.timeout_ms = SDMMC_WRITE_CMD_TIMEOUT_MS
|
||||||
};
|
};
|
||||||
if (block_count == 1) {
|
if (block_count == 1) {
|
||||||
cmd.opcode = MMC_WRITE_BLOCK_SINGLE;
|
cmd.opcode = MMC_WRITE_BLOCK_SINGLE;
|
||||||
|
@@ -54,6 +54,15 @@ void app_main(void)
|
|||||||
// Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals.
|
// Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals.
|
||||||
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
|
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
|
||||||
|
|
||||||
|
// GPIOs 15, 2, 4, 12, 13 should have external 10k pull-ups.
|
||||||
|
// Internal pull-ups are not sufficient. However, enabling internal pull-ups
|
||||||
|
// does make a difference some boards, so we do that here.
|
||||||
|
gpio_set_pull_mode(15, GPIO_PULLUP_ONLY); // CMD, needed in 4- and 1- line modes
|
||||||
|
gpio_set_pull_mode(2, GPIO_PULLUP_ONLY); // D0, needed in 4- and 1-line modes
|
||||||
|
gpio_set_pull_mode(4, GPIO_PULLUP_ONLY); // D1, needed in 4-line mode only
|
||||||
|
gpio_set_pull_mode(12, GPIO_PULLUP_ONLY); // D2, needed in 4-line mode only
|
||||||
|
gpio_set_pull_mode(13, GPIO_PULLUP_ONLY); // D3, needed in 4- and 1-line modes
|
||||||
|
|
||||||
#else
|
#else
|
||||||
ESP_LOGI(TAG, "Using SPI peripheral");
|
ESP_LOGI(TAG, "Using SPI peripheral");
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user