sdspi_transaction.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. // Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include <string.h>
  15. #include "esp_err.h"
  16. #include "esp_log.h"
  17. #include "sys/lock.h"
  18. #include "driver/sdmmc_types.h"
  19. #include "driver/sdmmc_defs.h"
  20. #include "driver/sdmmc_types.h"
  21. #include "sdspi_private.h"
  22. #include "sdspi_crc.h"
  23. static const char* TAG = "sdspi_transaction";
  24. static _lock_t s_lock;
  25. static bool s_app_cmd;
  26. static uint8_t sdspi_msg_crc7(sdspi_hw_cmd_t* hw_cmd)
  27. {
  28. const size_t bytes_to_crc = offsetof(sdspi_hw_cmd_t, arguments) +
  29. sizeof(hw_cmd->arguments); /* can't take address of bit fields */
  30. return sdspi_crc7((const uint8_t *)hw_cmd, bytes_to_crc);
  31. }
  32. void make_hw_cmd(uint32_t opcode, uint32_t arg, int timeout_ms, sdspi_hw_cmd_t *hw_cmd)
  33. {
  34. hw_cmd->start_bit = 0;
  35. hw_cmd->transmission_bit = 1;
  36. hw_cmd->cmd_index = opcode;
  37. hw_cmd->stop_bit = 1;
  38. hw_cmd->r1 = 0xff;
  39. memset(hw_cmd->response, 0xff, sizeof(hw_cmd->response));
  40. hw_cmd->ncr = 0xff;
  41. uint32_t arg_s = __builtin_bswap32(arg);
  42. memcpy(hw_cmd->arguments, &arg_s, sizeof(arg_s));
  43. hw_cmd->crc7 = sdspi_msg_crc7(hw_cmd);
  44. hw_cmd->timeout_ms = timeout_ms;
  45. }
  46. static void r1_response_to_err(uint8_t r1, int cmd, esp_err_t *out_err)
  47. {
  48. if (r1 & SD_SPI_R1_NO_RESPONSE) {
  49. ESP_LOGD(TAG, "cmd=%d, R1 response not found", cmd);
  50. *out_err = ESP_ERR_TIMEOUT;
  51. } else if (r1 & SD_SPI_R1_CMD_CRC_ERR) {
  52. ESP_LOGD(TAG, "cmd=%d, R1 response: command CRC error", cmd);
  53. *out_err = ESP_ERR_INVALID_CRC;
  54. } else if (r1 & SD_SPI_R1_ILLEGAL_CMD) {
  55. ESP_LOGD(TAG, "cmd=%d, R1 response: command not supported", cmd);
  56. *out_err = ESP_ERR_NOT_SUPPORTED;
  57. } else if (r1 & SD_SPI_R1_ADDR_ERR) {
  58. ESP_LOGD(TAG, "cmd=%d, R1 response: alignment error", cmd);
  59. *out_err = ESP_ERR_INVALID_ARG;
  60. } else if (r1 & SD_SPI_R1_PARAM_ERR) {
  61. ESP_LOGD(TAG, "cmd=%d, R1 response: size error", cmd);
  62. *out_err = ESP_ERR_INVALID_SIZE;
  63. } else if ((r1 & SD_SPI_R1_ERASE_RST) ||
  64. (r1 & SD_SPI_R1_ERASE_SEQ_ERR)) {
  65. *out_err = ESP_ERR_INVALID_STATE;
  66. } else if (r1 & SD_SPI_R1_IDLE_STATE) {
  67. // Idle state is handled at command layer
  68. } else if (r1 != 0) {
  69. ESP_LOGD(TAG, "cmd=%d, R1 response: unexpected value 0x%02x", cmd, r1);
  70. *out_err = ESP_ERR_INVALID_RESPONSE;
  71. }
  72. }
  73. static void r1_sdio_response_to_err(uint8_t r1, int cmd, esp_err_t *out_err)
  74. {
  75. if (r1 & SD_SPI_R1_NO_RESPONSE) {
  76. ESP_LOGI(TAG, "cmd=%d, R1 response not found", cmd);
  77. *out_err = ESP_ERR_TIMEOUT;
  78. } else if (r1 & SD_SPI_R1_CMD_CRC_ERR) {
  79. ESP_LOGI(TAG, "cmd=%d, R1 response: command CRC error", cmd);
  80. *out_err = ESP_ERR_INVALID_CRC;
  81. } else if (r1 & SD_SPI_R1_ILLEGAL_CMD) {
  82. ESP_LOGI(TAG, "cmd=%d, R1 response: command not supported", cmd);
  83. *out_err = ESP_ERR_NOT_SUPPORTED;
  84. } else if (r1 & SD_SPI_R1_PARAM_ERR) {
  85. ESP_LOGI(TAG, "cmd=%d, R1 response: size error", cmd);
  86. *out_err = ESP_ERR_INVALID_SIZE;
  87. } else if (r1 & SDIO_R1_FUNC_NUM_ERR) {
  88. ESP_LOGI(TAG, "cmd=%d, R1 response: function number error", cmd);
  89. *out_err = ESP_ERR_INVALID_ARG;
  90. } else if (r1 & SD_SPI_R1_IDLE_STATE) {
  91. // Idle state is handled at command layer
  92. } else if (r1 != 0) {
  93. ESP_LOGI(TAG, "cmd=%d, R1 response: unexpected value 0x%02x", cmd, r1);
  94. *out_err = ESP_ERR_INVALID_RESPONSE;
  95. }
  96. }
  97. esp_err_t sdspi_host_do_transaction(int slot, sdmmc_command_t *cmdinfo)
  98. {
  99. _lock_acquire(&s_lock);
  100. // Convert the command to wire format
  101. WORD_ALIGNED_ATTR sdspi_hw_cmd_t hw_cmd;
  102. make_hw_cmd(cmdinfo->opcode, cmdinfo->arg, cmdinfo->timeout_ms, &hw_cmd);
  103. // Flags indicate which of the transfer types should be used
  104. int flags = 0;
  105. if (SCF_CMD(cmdinfo->flags) == SCF_CMD_ADTC) {
  106. flags = SDSPI_CMD_FLAG_DATA | SDSPI_CMD_FLAG_WRITE;
  107. } else if (SCF_CMD(cmdinfo->flags) == (SCF_CMD_ADTC | SCF_CMD_READ)) {
  108. flags = SDSPI_CMD_FLAG_DATA;
  109. }
  110. // The block size is 512, when larger than 512, the data must send in multi blocks
  111. if (cmdinfo->datalen > SDSPI_MAX_DATA_LEN) {
  112. flags |= SDSPI_CMD_FLAG_MULTI_BLK;
  113. }
  114. // In SD host, response format is encoded using SCF_RSP_* flags which come
  115. // as part of sdmmc_command_t from the upper layer (sdmmc_cmd.c).
  116. // SPI mode uses different command formats. In fact, most of the commands
  117. // use R1 response. Therefore, instead of adding another parallel set of
  118. // response flags for the SPI mode, response format is determined here:
  119. if (!s_app_cmd && cmdinfo->opcode == SD_SEND_IF_COND) {
  120. flags |= SDSPI_CMD_FLAG_RSP_R7;
  121. } else if (!s_app_cmd && cmdinfo->opcode == MMC_SEND_STATUS) {
  122. flags |= SDSPI_CMD_FLAG_RSP_R2;
  123. } else if (!s_app_cmd && cmdinfo->opcode == SD_READ_OCR) {
  124. flags |= SDSPI_CMD_FLAG_RSP_R3;
  125. } else if (s_app_cmd && cmdinfo->opcode == SD_APP_SD_STATUS) {
  126. flags |= SDSPI_CMD_FLAG_RSP_R2;
  127. } else if (!s_app_cmd && cmdinfo->opcode == MMC_GO_IDLE_STATE &&
  128. !(cmdinfo->flags & SCF_RSP_R1)) {
  129. /* used to send CMD0 without expecting a response */
  130. flags |= SDSPI_CMD_FLAG_NORSP;
  131. } else if (!s_app_cmd && cmdinfo->opcode == SD_IO_SEND_OP_COND) {
  132. flags |= SDSPI_CMD_FLAG_RSP_R4;
  133. } else if (!s_app_cmd && cmdinfo->opcode == SD_IO_RW_DIRECT) {
  134. flags |= SDSPI_CMD_FLAG_RSP_R5;
  135. } else if (!s_app_cmd && cmdinfo->opcode == SD_IO_RW_EXTENDED) {
  136. flags |= SDSPI_CMD_FLAG_RSP_R5 | SDSPI_CMD_FLAG_DATA;
  137. if (cmdinfo->arg & SD_ARG_CMD53_WRITE) flags |= SDSPI_CMD_FLAG_WRITE;
  138. // The CMD53 can assign block mode in the arg when the length is exactly 512 bytes
  139. if (cmdinfo->arg & SD_ARG_CMD53_BLOCK_MODE) flags |= SDSPI_CMD_FLAG_MULTI_BLK;
  140. } else {
  141. flags |= SDSPI_CMD_FLAG_RSP_R1;
  142. }
  143. // Send the command and get the response.
  144. esp_err_t ret = sdspi_host_start_command(slot, &hw_cmd,
  145. cmdinfo->data, cmdinfo->datalen, flags);
  146. // Extract response bytes and store them into cmdinfo structure
  147. if (ret == ESP_OK) {
  148. ESP_LOGV(TAG, "r1 = 0x%02x hw_cmd.r[0]=0x%08x", hw_cmd.r1, hw_cmd.response[0]);
  149. // Some errors should be reported using return code
  150. if (flags & SDSPI_CMD_FLAG_RSP_R1) {
  151. cmdinfo->response[0] = hw_cmd.r1;
  152. r1_response_to_err(hw_cmd.r1, cmdinfo->opcode, &ret);
  153. } else if (flags & SDSPI_CMD_FLAG_RSP_R2) {
  154. cmdinfo->response[0] = (((uint32_t)hw_cmd.r1) << 8) | (hw_cmd.response[0] >> 24);
  155. } else if (flags & (SDSPI_CMD_FLAG_RSP_R3 | SDSPI_CMD_FLAG_RSP_R7)) {
  156. r1_response_to_err(hw_cmd.r1, cmdinfo->opcode, &ret);
  157. cmdinfo->response[0] = __builtin_bswap32(hw_cmd.response[0]);
  158. } else if (flags & SDSPI_CMD_FLAG_RSP_R4) {
  159. r1_sdio_response_to_err(hw_cmd.r1, cmdinfo->opcode, &ret);
  160. cmdinfo->response[0] = __builtin_bswap32(hw_cmd.response[0]);
  161. } else if (flags & SDSPI_CMD_FLAG_RSP_R5) {
  162. r1_sdio_response_to_err(hw_cmd.r1, cmdinfo->opcode, &ret);
  163. cmdinfo->response[0] = hw_cmd.response[0];
  164. }
  165. }
  166. // Save a flag whether the next command is expected to be an app command
  167. if (ret == ESP_OK) {
  168. s_app_cmd = (cmdinfo->opcode == MMC_APP_CMD);
  169. } else {
  170. s_app_cmd = false;
  171. }
  172. _lock_release(&s_lock);
  173. return ret;
  174. }