فهرست منبع

Merge branch 'bugfix/sd_card_fixes' into 'master'

SD card fixes

See merge request !1393

Ivan Grokhotkov 8 سال پیش
والد
کامیت
edb212986f

+ 2 - 0
components/driver/include/driver/sdmmc_types.h

@@ -102,6 +102,7 @@ typedef struct {
 #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)
         esp_err_t error;            /*!< error returned from transfer */
+        int timeout_ms;             /*!< response timeout, in milliseconds */
 } 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 (*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 */
+    int command_timeout_ms;     /*!< timeout, in milliseconds, of a single command. Set to 0 to use the default value. */
 } sdmmc_host_t;
 
 /**

+ 1 - 8
components/driver/sdmmc_transaction.c

@@ -33,13 +33,6 @@
  */
 #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";
 
 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)
 {
     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) {
         ESP_LOGE(TAG, "sdmmc_host_wait_for_event returned 0x%x", err);
         if (err == ESP_ERR_TIMEOUT) {

+ 18 - 3
components/sdmmc/sdmmc_cmd.c

@@ -28,6 +28,14 @@
 
 #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 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)
 {
+    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;
-    ESP_LOGV(TAG, "sending cmd slot=%d op=%d arg=%x flags=%x data=%p blklen=%d datalen=%d",
-            slot, cmd->opcode, cmd->arg, cmd->flags, cmd->data, cmd->blklen, cmd->datalen);
+    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, cmd->timeout_ms);
     esp_err_t err = (*card->host.do_transaction)(slot, cmd);
     if (err != 0) {
         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,
             .blklen = block_size,
             .data = (void*) src,
-            .datalen = block_count * block_size
+            .datalen = block_count * block_size,
+            .timeout_ms = SDMMC_WRITE_CMD_TIMEOUT_MS
     };
     if (block_count == 1) {
         cmd.opcode = MMC_WRITE_BLOCK_SINGLE;

+ 9 - 0
examples/storage/sd_card/main/sd_card_example_main.c

@@ -54,6 +54,15 @@ void app_main(void)
     // 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();
 
+    // 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
     ESP_LOGI(TAG, "Using SPI peripheral");