Selaa lähdekoodia

sdspi: handle delayed responses for data write commands

Command response tokens can be delayed from the original command by 1
to 8 bytes. In 4a2489b9, handling for delayed tokens was added for
normal (no data) commands, and data read commands. This adds handling
for delayed commands for data write commands.
Ivan Grokhotkov 7 vuotta sitten
vanhempi
sitoutus
2699bb49ae
1 muutettua tiedostoa jossa 45 lisäystä ja 28 poistoa
  1. 45 28
      components/driver/sdspi_host.c

+ 45 - 28
components/driver/sdspi_host.c

@@ -67,6 +67,8 @@ static esp_err_t start_command_write_blocks(int slot, sdspi_hw_cmd_t *cmd,
 
 static esp_err_t start_command_default(int slot, int flags, sdspi_hw_cmd_t *cmd);
 
+static esp_err_t poll_cmd_response(int slot, sdspi_hw_cmd_t *cmd);
+
 /// A few helper functions
 
 /// Set CS high for given slot
@@ -429,32 +431,21 @@ static esp_err_t start_command_default(int slot, int flags, sdspi_hw_cmd_t *cmd)
         /* response is a stuff byte from previous transfer, ignore it */
         cmd->r1 = 0xff;
     }
+    if (ret != ESP_OK) {
+        ESP_LOGD(TAG, "%s: spi_device_transmit returned 0x%x", __func__, ret);
+        return ret;
+    }
     if (flags & SDSPI_CMD_FLAG_NORSP) {
         /* no (correct) response expected from the card, so skip polling loop */
         ESP_LOGV(TAG, "%s: ignoring response byte", __func__);
         cmd->r1 = 0x00;
     }
-    int response_delay_bytes = SDSPI_RESPONSE_MAX_DELAY;
-    while ((cmd->r1 & SD_SPI_R1_NO_RESPONSE) != 0 && response_delay_bytes-- > 0) {
-        spi_transaction_t* t = get_transaction(slot);
-        *t = (spi_transaction_t) {
-            .flags = SPI_TRANS_USE_RXDATA | SPI_TRANS_USE_TXDATA,
-            .length = 8,
-        };
-        t->tx_data[0] = 0xff;
-        ret = spi_device_transmit(spi_handle(slot), t);
-        uint8_t r1 = t->rx_data[0];
-        release_transaction(slot);
-        if (ret != ESP_OK) {
-            return ret;
-        }
-        cmd->r1 = r1;
-    }
-    if (cmd->r1 & SD_SPI_R1_NO_RESPONSE) {
-        ESP_LOGD(TAG, "%s: no response token found", __func__);
-        return ESP_ERR_TIMEOUT;
+    ret = poll_cmd_response(slot, cmd);
+    if (ret != ESP_OK) {
+        ESP_LOGD(TAG, "%s: poll_cmd_response returned 0x%x", __func__, ret);
+        return ret;
     }
-    return ret;
+    return ESP_OK;
 }
 
 // Wait until MISO goes high
@@ -563,6 +554,30 @@ static esp_err_t poll_data_token(int slot, spi_transaction_t* t,
     return ESP_ERR_TIMEOUT;
 }
 
+static esp_err_t poll_cmd_response(int slot, sdspi_hw_cmd_t *cmd)
+{
+    int response_delay_bytes = SDSPI_RESPONSE_MAX_DELAY;
+    while ((cmd->r1 & SD_SPI_R1_NO_RESPONSE) != 0 && response_delay_bytes-- > 0) {
+        spi_transaction_t* t = get_transaction(slot);
+        *t = (spi_transaction_t) {
+            .flags = SPI_TRANS_USE_RXDATA | SPI_TRANS_USE_TXDATA,
+            .length = 8,
+        };
+        t->tx_data[0] = 0xff;
+        esp_err_t ret = spi_device_transmit(spi_handle(slot), t);
+        uint8_t r1 = t->rx_data[0];
+        release_transaction(slot);
+        if (ret != ESP_OK) {
+            return ret;
+        }
+        cmd->r1 = r1;
+    }
+    if (cmd->r1 & SD_SPI_R1_NO_RESPONSE) {
+        return ESP_ERR_TIMEOUT;
+    }
+    return ESP_OK;
+}
+
 
 /**
  * Receiving one or more blocks of data happens as follows:
@@ -759,9 +774,17 @@ static esp_err_t start_command_write_blocks(int slot, sdspi_hw_cmd_t *cmd,
     if (ret != ESP_OK) {
         return ret;
     }
+    wait_for_transactions(slot);
+
+    // Poll for command response which may be delayed up to 8 bytes
+    ret = poll_cmd_response(slot, cmd);
+    if (ret != ESP_OK) {
+        ESP_LOGD(TAG, "%s: poll_cmd_response returned 0x%x", __func__, ret);
+        return ret;
+    }
+
     uint8_t start_token = tx_length <= SDSPI_MAX_DATA_LEN ?
             TOKEN_BLOCK_START : TOKEN_BLOCK_START_WRITE_MULTI;
-    wait_for_transactions(slot);
 
     while (tx_length > 0) {
 
@@ -771,7 +794,7 @@ static esp_err_t start_command_write_blocks(int slot, sdspi_hw_cmd_t *cmd,
             .length = sizeof(start_token) * 8,
             .tx_buffer = &start_token
         };
-        esp_err_t ret = spi_device_queue_trans(spi_handle(slot), t_start_token, 0);
+        ret = spi_device_queue_trans(spi_handle(slot), t_start_token, 0);
         if (ret != ESP_OK) {
             return ret;
         }
@@ -816,12 +839,6 @@ static esp_err_t start_command_write_blocks(int slot, sdspi_hw_cmd_t *cmd,
         // Wait for data to be sent
         wait_for_transactions(slot);
 
-        // Check if R1 response for the command was correct
-        if (cmd->r1 != 0) {
-            ESP_LOGD(TAG, "%s: invalid R1 response: 0x%02x", __func__, cmd->r1);
-            return ESP_ERR_INVALID_RESPONSE;
-        }
-
         // Poll for response
         spi_transaction_t* t_poll = get_transaction(slot);
         ret = poll_response_token(slot, t_poll, cmd->timeout_ms);