diff --git a/components/driver/include/driver/sdmmc_defs.h b/components/driver/include/driver/sdmmc_defs.h index c13df6d1a..96e0743d5 100644 --- a/components/driver/include/driver/sdmmc_defs.h +++ b/components/driver/include/driver/sdmmc_defs.h @@ -86,7 +86,13 @@ /* 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]) diff --git a/components/driver/sdspi_transaction.c b/components/driver/sdspi_transaction.c index 64271749a..728979b33 100644 --- a/components/driver/sdspi_transaction.c +++ b/components/driver/sdspi_transaction.c @@ -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]); } } diff --git a/components/sdmmc/sdmmc_cmd.c b/components/sdmmc/sdmmc_cmd.c index 594e46976..2c58843c2 100644 --- a/components/sdmmc/sdmmc_cmd.c +++ b/components/sdmmc/sdmmc_cmd.c @@ -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;