]> granicus.if.org Git - esp-idf/commitdiff
sdspi: handle error flags for R3/R7 responses
authorIvan Grokhotkov <ivan@espressif.com>
Tue, 6 Feb 2018 02:53:41 +0000 (10:53 +0800)
committerIvan Grokhotkov <ivan@espressif.com>
Fri, 30 Mar 2018 10:49:42 +0000 (18:49 +0800)
Previously error flags were only handled for R1 responses. This change
moves error handling into a separate function and calls it for R1/R3/R7.

components/driver/include/driver/sdmmc_defs.h
components/driver/sdspi_transaction.c
components/sdmmc/sdmmc_cmd.c

index c13df6d1aaf429988415bdbe9df8d4bc292a7384..96e0743d5fd568097b5dbf3d83c3b223d35f7aa8 100644 (file)
 
 /* SPI mode R1 response type bits */
 #define SD_SPI_R1_IDLE_STATE            (1<<0)
+#define SD_SPI_R1_ERASE_RST             (1<<1)
+#define SD_SPI_R1_ILLEGAL_CMD           (1<<2)
 #define SD_SPI_R1_CMD_CRC_ERR           (1<<3)
+#define SD_SPI_R1_ERASE_SEQ_ERR         (1<<4)
+#define SD_SPI_R1_ADDR_ERR              (1<<5)
+#define SD_SPI_R1_PARAM_ERR             (1<<6)
+#define SD_SPI_R1_NO_RESPONSE           (1<<7)
 
 /* 48-bit response decoding (32 bits w/o CRC) */
 #define MMC_R1(resp)                    ((resp)[0])
index 64271749ad5047f7dfba84c77b4d6dba2a38f85c..728979b3337156911f04bf70c49e02e3c7e64c14 100644 (file)
@@ -51,6 +51,34 @@ void make_hw_cmd(uint32_t opcode, uint32_t arg, int timeout_ms, sdspi_hw_cmd_t *
     hw_cmd->timeout_ms = timeout_ms;
 }
 
+static void r1_response_to_err(uint8_t r1, esp_err_t *out_err)
+{
+    if (r1 & SD_SPI_R1_NO_RESPONSE) {
+        ESP_LOGD(TAG, "R1 response not found");
+        *out_err = ESP_ERR_TIMEOUT;
+    } else if (r1 & SD_SPI_R1_CMD_CRC_ERR) {
+        ESP_LOGD(TAG, "R1 response: command CRC error");
+        *out_err = ESP_ERR_INVALID_CRC;
+    } else if (r1 & SD_SPI_R1_ILLEGAL_CMD) {
+        ESP_LOGD(TAG, "R1 response: command not supported");
+        *out_err = ESP_ERR_NOT_SUPPORTED;
+    } else if (r1 & SD_SPI_R1_ADDR_ERR) {
+        ESP_LOGD(TAG, "R1 response: alignment error");
+        *out_err = ESP_ERR_INVALID_ARG;
+    } else if (r1 & SD_SPI_R1_PARAM_ERR) {
+        ESP_LOGD(TAG, "R1 response: size error");
+        *out_err = ESP_ERR_INVALID_SIZE;
+    } else if ((r1 & SD_SPI_R1_ERASE_RST) ||
+               (r1 & SD_SPI_R1_ERASE_SEQ_ERR)) {
+        *out_err = ESP_ERR_INVALID_STATE;
+    } else if (r1 & SD_SPI_R1_IDLE_STATE) {
+        // Idle state is handled at command layer
+    } else if (r1 != 0) {
+        ESP_LOGD(TAG, "R1 response: unexpected value 0x%02x", r1);
+        *out_err = ESP_ERR_INVALID_RESPONSE;
+    }
+}
+
 esp_err_t sdspi_host_do_transaction(int slot, sdmmc_command_t *cmdinfo)
 {
     _lock_acquire(&s_lock);
@@ -93,21 +121,11 @@ esp_err_t sdspi_host_do_transaction(int slot, sdmmc_command_t *cmdinfo)
         // Some errors should be reported using return code
         if (flags & SDSPI_CMD_FLAG_RSP_R1) {
             cmdinfo->response[0] = hw_cmd.r1;
-            if (hw_cmd.r1 == 0xff) {
-                // No response received at all
-            } else if (hw_cmd.r1 & SD_SPI_R1_CMD_CRC_ERR) {
-                ret = ESP_ERR_INVALID_CRC;
-            } else if (hw_cmd.r1 & SD_SPI_R1_IDLE_STATE) {
-                // Idle state is handled at command layer
-            } else if (hw_cmd.r1 != 0) {
-                ESP_LOGD(TAG, "Unexpected R1 response: 0x%02x", hw_cmd.r1);
-            }
+            r1_response_to_err(hw_cmd.r1, &ret);
         } else if (flags & SDSPI_CMD_FLAG_RSP_R2) {
             cmdinfo->response[0] = (((uint32_t)hw_cmd.r1) << 8) | (hw_cmd.response[0] >> 24);
         } else if (flags & (SDSPI_CMD_FLAG_RSP_R3 | SDSPI_CMD_FLAG_RSP_R7)) {
-            // Drop r1 response, only copy the other 4 bytes of data
-            // TODO: can we somehow preserve r1 response and keep upper layer
-            // same as in SD mode?
+            r1_response_to_err(hw_cmd.r1, &ret);
             cmdinfo->response[0] = __builtin_bswap32(hw_cmd.response[0]);
         }
     }
index 594e46976753141304a7e14a3eb70e1ab384ebf7..2c58843c2d8b4ed91dca60e4f68cff2c3c2fcb6f 100644 (file)
@@ -112,7 +112,9 @@ esp_err_t sdmmc_card_init(const sdmmc_host_t* config, sdmmc_card_t* card)
         ESP_LOGD(TAG, "SDHC/SDXC card");
         host_ocr |= SD_OCR_SDHC_CAP;
     } else if (err == ESP_ERR_TIMEOUT) {
-        ESP_LOGD(TAG, "CMD8 timeout; not an SDHC/SDXC card");
+        ESP_LOGD(TAG, "CMD8 timeout; not an SD v2.00 card");
+    } else if (is_spi && err == ESP_ERR_NOT_SUPPORTED) {
+        ESP_LOGD(TAG, "CMD8 rejected; not an SD v2.00 card");
     } else {
         ESP_LOGE(TAG, "%s: send_if_cond (1) returned 0x%x", __func__, err);
         return err;