Просмотр исходного кода

sdmmc: enable host auto_stop only for certain commands

Perviously host send_auto_stop flag would be set for every data
transfer over 1 block long. This caused stop commands to be sent
after CMD53, which shouldn't be done. Fix by adding an explicit list
of commands for which send_auto_stop should be set.
Ivan Grokhotkov 7 лет назад
Родитель
Сommit
6d46eed8e4

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

@@ -31,11 +31,13 @@
 #define MMC_SEND_EXT_CSD                8       /* R1 */
 #define MMC_SEND_CSD                    9       /* R2 */
 #define MMC_SEND_CID                    10      /* R1 */
+#define MMC_READ_DAT_UNTIL_STOP         11      /* R1 */
 #define MMC_STOP_TRANSMISSION           12      /* R1B */
 #define MMC_SEND_STATUS                 13      /* R1 */
 #define MMC_SET_BLOCKLEN                16      /* R1 */
 #define MMC_READ_BLOCK_SINGLE           17      /* R1 */
 #define MMC_READ_BLOCK_MULTIPLE         18      /* R1 */
+#define MMC_WRITE_DAT_UNTIL_STOP        20      /* R1 */
 #define MMC_SET_BLOCK_COUNT             23      /* R1 */
 #define MMC_WRITE_BLOCK_SINGLE          24      /* R1 */
 #define MMC_WRITE_BLOCK_MULTIPLE        25      /* R1 */

+ 14 - 5
components/driver/sdmmc_transaction.c

@@ -271,6 +271,16 @@ static esp_err_t handle_event(sdmmc_command_t* cmd, sdmmc_req_state_t* state,
     return ESP_OK;
 }
 
+static bool cmd_needs_auto_stop(const sdmmc_command_t* cmd)
+{
+    /* SDMMC host needs an "auto stop" flag for the following commands: */
+    return cmd->datalen > 0 &&
+           (cmd->opcode == MMC_WRITE_BLOCK_MULTIPLE ||
+            cmd->opcode == MMC_READ_BLOCK_MULTIPLE ||
+            cmd->opcode == MMC_WRITE_DAT_UNTIL_STOP ||
+            cmd->opcode == MMC_READ_DAT_UNTIL_STOP);
+}
+
 static sdmmc_hw_cmd_t make_hw_cmd(sdmmc_command_t* cmd)
 {
     sdmmc_hw_cmd_t res = { 0 };
@@ -302,12 +312,11 @@ static sdmmc_hw_cmd_t make_hw_cmd(sdmmc_command_t* cmd)
             res.rw = 1;
         }
         assert(cmd->datalen % cmd->blklen == 0);
-        if ((cmd->datalen / cmd->blklen) > 1) {
-            res.send_auto_stop = 1;
-        }
+        res.send_auto_stop = cmd_needs_auto_stop(cmd) ? 1 : 0;
     }
-    ESP_LOGV(TAG, "%s: opcode=%d, rexp=%d, crc=%d", __func__,
-            res.cmd_index, res.response_expect, res.check_response_crc);
+    ESP_LOGV(TAG, "%s: opcode=%d, rexp=%d, crc=%d, auto_stop=%d", __func__,
+            res.cmd_index, res.response_expect, res.check_response_crc,
+            res.send_auto_stop);
     return res;
 }