Skip to content

Commit aca0008

Browse files
committed
Merge branch 'bugfix/sdspi_init_v1_card' into 'master'
sdspi: compatibility fixes for SD v1.0 cards See merge request idf/esp-idf!1927
2 parents 8eaae96 + d6b1d0b commit aca0008

File tree

5 files changed

+111
-38
lines changed

5 files changed

+111
-38
lines changed

components/driver/include/driver/sdmmc_defs.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,13 @@
8686

8787
/* SPI mode R1 response type bits */
8888
#define SD_SPI_R1_IDLE_STATE (1<<0)
89+
#define SD_SPI_R1_ERASE_RST (1<<1)
90+
#define SD_SPI_R1_ILLEGAL_CMD (1<<2)
8991
#define SD_SPI_R1_CMD_CRC_ERR (1<<3)
92+
#define SD_SPI_R1_ERASE_SEQ_ERR (1<<4)
93+
#define SD_SPI_R1_ADDR_ERR (1<<5)
94+
#define SD_SPI_R1_PARAM_ERR (1<<6)
95+
#define SD_SPI_R1_NO_RESPONSE (1<<7)
9096

9197
/* 48-bit response decoding (32 bits w/o CRC) */
9298
#define MMC_R1(resp) ((resp)[0])

components/driver/sdspi_host.c

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
#define GPIO_UNUSED 0xff //!< Flag indicating that CD/WP is unused
3535
/// Size of the buffer returned by get_block_buf
3636
#define SDSPI_BLOCK_BUF_SIZE (SDSPI_MAX_DATA_LEN + 4)
37+
/// Maximum number of dummy bytes between the request and response (minimum is 1)
38+
#define SDSPI_RESPONSE_MAX_DELAY 8
3739

3840

3941
/// Structure containing run time configuration for a single SD slot
@@ -422,6 +424,30 @@ static esp_err_t start_command_default(int slot, int flags, sdspi_hw_cmd_t *cmd)
422424
.rx_buffer = cmd
423425
};
424426
esp_err_t ret = spi_device_transmit(spi_handle(slot), &t);
427+
if (cmd->cmd_index == MMC_STOP_TRANSMISSION) {
428+
/* response is a stuff byte from previous transfer, ignore it */
429+
cmd->r1 = 0xff;
430+
}
431+
int response_delay_bytes = SDSPI_RESPONSE_MAX_DELAY;
432+
while ((cmd->r1 & SD_SPI_R1_NO_RESPONSE) != 0 && response_delay_bytes-- > 0) {
433+
spi_transaction_t* t = get_transaction(slot);
434+
*t = (spi_transaction_t) {
435+
.flags = SPI_TRANS_USE_RXDATA | SPI_TRANS_USE_TXDATA,
436+
.length = 8,
437+
};
438+
t->tx_data[0] = 0xff;
439+
ret = spi_device_transmit(spi_handle(slot), t);
440+
uint8_t r1 = t->rx_data[0];
441+
release_transaction(slot);
442+
if (ret != ESP_OK) {
443+
return ret;
444+
}
445+
cmd->r1 = r1;
446+
}
447+
if (cmd->r1 & SD_SPI_R1_NO_RESPONSE) {
448+
ESP_LOGD(TAG, "%s: no response token found", __func__);
449+
return ESP_ERR_TIMEOUT;
450+
}
425451
return ret;
426452
}
427453

@@ -564,6 +590,9 @@ static esp_err_t poll_data_token(int slot, spi_transaction_t* t,
564590
* indicating the start of the next block. Actual scanning is done by
565591
* setting pre_scan_data_ptr to point to these last 2 bytes, and setting
566592
* pre_scan_data_size = 2, then going to step 2 to receive the next block.
593+
* When the final block is being received, the number of extra bytes is 2
594+
* (only for CRC), because we don't need to wait for start token of the
595+
* next block, and some cards are getting confused by these two extra bytes.
567596
*
568597
* With this approach the delay between blocks of a multi-block transfer is
569598
* ~95 microseconds, out of which 35 microseconds are spend doing the CRC check.
@@ -576,7 +605,7 @@ static esp_err_t start_command_read_blocks(int slot, sdspi_hw_cmd_t *cmd,
576605
bool need_stop_command = rx_length > SDSPI_MAX_DATA_LEN;
577606
spi_transaction_t* t_command = get_transaction(slot);
578607
*t_command = (spi_transaction_t) {
579-
.length = (SDSPI_CMD_R1_SIZE + 8) * 8,
608+
.length = (SDSPI_CMD_R1_SIZE + SDSPI_RESPONSE_MAX_DELAY) * 8,
580609
.tx_buffer = cmd,
581610
.rx_buffer = cmd,
582611
};
@@ -587,9 +616,21 @@ static esp_err_t start_command_read_blocks(int slot, sdspi_hw_cmd_t *cmd,
587616
release_transaction(slot);
588617

589618
uint8_t* cmd_u8 = (uint8_t*) cmd;
590-
size_t pre_scan_data_size = 8;
619+
size_t pre_scan_data_size = SDSPI_RESPONSE_MAX_DELAY;
591620
uint8_t* pre_scan_data_ptr = cmd_u8 + SDSPI_CMD_R1_SIZE;
592621

622+
/* R1 response is delayed by 1-8 bytes from the request.
623+
* This loop searches for the response and writes it to cmd->r1.
624+
*/
625+
while ((cmd->r1 & SD_SPI_R1_NO_RESPONSE) != 0 && pre_scan_data_size > 0) {
626+
cmd->r1 = *pre_scan_data_ptr;
627+
++pre_scan_data_ptr;
628+
--pre_scan_data_size;
629+
}
630+
if (cmd->r1 & SD_SPI_R1_NO_RESPONSE) {
631+
ESP_LOGD(TAG, "no response token found");
632+
return ESP_ERR_TIMEOUT;
633+
}
593634

594635
while (rx_length > 0) {
595636
size_t extra_data_size = 0;
@@ -627,7 +668,7 @@ static esp_err_t start_command_read_blocks(int slot, sdspi_hw_cmd_t *cmd,
627668
}
628669

629670
// receive actual data
630-
const size_t receive_extra_bytes = 4;
671+
const size_t receive_extra_bytes = (rx_length > SDSPI_MAX_DATA_LEN) ? 4 : 2;
631672
memset(rx_data, 0xff, will_receive + receive_extra_bytes);
632673
spi_transaction_t* t_data = get_transaction(slot);
633674
*t_data = (spi_transaction_t) {
@@ -682,6 +723,9 @@ static esp_err_t start_command_read_blocks(int slot, sdspi_hw_cmd_t *cmd,
682723
if (ret != ESP_OK) {
683724
return ret;
684725
}
726+
if (stop_cmd.r1 != 0) {
727+
ESP_LOGD(TAG, "%s: STOP_TRANSMISSION response 0x%02x", __func__, stop_cmd.r1);
728+
}
685729
spi_transaction_t* t_poll = get_transaction(slot);
686730
ret = poll_busy(slot, t_poll, cmd->timeout_ms);
687731
release_transaction(slot);

components/driver/sdspi_transaction.c

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,34 @@ void make_hw_cmd(uint32_t opcode, uint32_t arg, int timeout_ms, sdspi_hw_cmd_t *
5151
hw_cmd->timeout_ms = timeout_ms;
5252
}
5353

54+
static void r1_response_to_err(uint8_t r1, esp_err_t *out_err)
55+
{
56+
if (r1 & SD_SPI_R1_NO_RESPONSE) {
57+
ESP_LOGD(TAG, "R1 response not found");
58+
*out_err = ESP_ERR_TIMEOUT;
59+
} else if (r1 & SD_SPI_R1_CMD_CRC_ERR) {
60+
ESP_LOGD(TAG, "R1 response: command CRC error");
61+
*out_err = ESP_ERR_INVALID_CRC;
62+
} else if (r1 & SD_SPI_R1_ILLEGAL_CMD) {
63+
ESP_LOGD(TAG, "R1 response: command not supported");
64+
*out_err = ESP_ERR_NOT_SUPPORTED;
65+
} else if (r1 & SD_SPI_R1_ADDR_ERR) {
66+
ESP_LOGD(TAG, "R1 response: alignment error");
67+
*out_err = ESP_ERR_INVALID_ARG;
68+
} else if (r1 & SD_SPI_R1_PARAM_ERR) {
69+
ESP_LOGD(TAG, "R1 response: size error");
70+
*out_err = ESP_ERR_INVALID_SIZE;
71+
} else if ((r1 & SD_SPI_R1_ERASE_RST) ||
72+
(r1 & SD_SPI_R1_ERASE_SEQ_ERR)) {
73+
*out_err = ESP_ERR_INVALID_STATE;
74+
} else if (r1 & SD_SPI_R1_IDLE_STATE) {
75+
// Idle state is handled at command layer
76+
} else if (r1 != 0) {
77+
ESP_LOGD(TAG, "R1 response: unexpected value 0x%02x", r1);
78+
*out_err = ESP_ERR_INVALID_RESPONSE;
79+
}
80+
}
81+
5482
esp_err_t sdspi_host_do_transaction(int slot, sdmmc_command_t *cmdinfo)
5583
{
5684
_lock_acquire(&s_lock);
@@ -93,21 +121,11 @@ esp_err_t sdspi_host_do_transaction(int slot, sdmmc_command_t *cmdinfo)
93121
// Some errors should be reported using return code
94122
if (flags & SDSPI_CMD_FLAG_RSP_R1) {
95123
cmdinfo->response[0] = hw_cmd.r1;
96-
if (hw_cmd.r1 == 0xff) {
97-
// No response received at all
98-
} else if (hw_cmd.r1 & SD_SPI_R1_CMD_CRC_ERR) {
99-
ret = ESP_ERR_INVALID_CRC;
100-
} else if (hw_cmd.r1 & SD_SPI_R1_IDLE_STATE) {
101-
// Idle state is handled at command layer
102-
} else if (hw_cmd.r1 != 0) {
103-
ESP_LOGD(TAG, "Unexpected R1 response: 0x%02x", hw_cmd.r1);
104-
}
124+
r1_response_to_err(hw_cmd.r1, &ret);
105125
} else if (flags & SDSPI_CMD_FLAG_RSP_R2) {
106126
cmdinfo->response[0] = (((uint32_t)hw_cmd.r1) << 8) | (hw_cmd.response[0] >> 24);
107127
} else if (flags & (SDSPI_CMD_FLAG_RSP_R3 | SDSPI_CMD_FLAG_RSP_R7)) {
108-
// Drop r1 response, only copy the other 4 bytes of data
109-
// TODO: can we somehow preserve r1 response and keep upper layer
110-
// same as in SD mode?
128+
r1_response_to_err(hw_cmd.r1, &ret);
111129
cmdinfo->response[0] = __builtin_bswap32(hw_cmd.response[0]);
112130
}
113131
}

components/fatfs/test/test_fatfs_sdmmc.c

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ static void test_setup(void)
3939
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
4040
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
4141
.format_if_mount_failed = true,
42-
.max_files = 5
42+
.max_files = 5,
43+
.allocation_unit_size = 16 * 1024
4344
};
4445
TEST_ESP_OK(esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, NULL));
4546
}
@@ -50,9 +51,8 @@ static void test_teardown(void)
5051
}
5152

5253
static const char* test_filename = "/sdcard/hello.txt";
53-
static const char* test_filename_utf_8 = "/sdcard/测试文件.txt";
5454

55-
TEST_CASE("Mount fails cleanly without card inserted", "[fatfs][ignore]")
55+
TEST_CASE("Mount fails cleanly without card inserted", "[fatfs][sd][ignore]")
5656
{
5757
size_t heap_size;
5858
HEAP_SIZE_CAPTURE(heap_size);
@@ -64,22 +64,22 @@ TEST_CASE("Mount fails cleanly without card inserted", "[fatfs][ignore]")
6464
};
6565

6666
for (int i = 0; i < 3; ++i) {
67-
printf("Initializing card, attempt %d ", i);
67+
printf("Initializing card, attempt %d\n", i);
6868
esp_err_t err = esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, NULL);
69-
printf(" err=%d\n", err);
70-
TEST_ESP_ERR(ESP_FAIL, err);
69+
printf("err=%d\n", err);
70+
TEST_ESP_ERR(ESP_ERR_TIMEOUT, err);
7171
}
7272
HEAP_SIZE_CHECK(heap_size, 0);
7373
}
7474

75-
TEST_CASE("(SD) can create and write file", "[fatfs][sdcard][ignore]")
75+
TEST_CASE("(SD) can create and write file", "[fatfs][sd][test_env=UT_T1_SDMODE]")
7676
{
7777
test_setup();
7878
test_fatfs_create_file_with_text(test_filename, fatfs_test_hello_str);
7979
test_teardown();
8080
}
8181

82-
TEST_CASE("(SD) can read file", "[fatfs][ignore]")
82+
TEST_CASE("(SD) can read file", "[fatfs][test_env=UT_T1_SDMODE]")
8383
{
8484
test_setup();
8585
test_fatfs_create_file_with_text(test_filename, fatfs_test_hello_str);
@@ -88,64 +88,64 @@ TEST_CASE("(SD) can read file", "[fatfs][ignore]")
8888
}
8989

9090

91-
TEST_CASE("(SD) overwrite and append file", "[fatfs][sdcard][ignore]")
91+
TEST_CASE("(SD) overwrite and append file", "[fatfs][sd][test_env=UT_T1_SDMODE]")
9292
{
9393
test_setup();
9494
test_fatfs_overwrite_append(test_filename);
9595
test_teardown();
9696
}
9797

9898

99-
TEST_CASE("(SD) can lseek", "[fatfs][sdcard][ignore]")
99+
TEST_CASE("(SD) can lseek", "[fatfs][sd][test_env=UT_T1_SDMODE]")
100100
{
101101
test_setup();
102102
test_fatfs_lseek("/sdcard/seek.txt");
103103
test_teardown();
104104
}
105105

106-
TEST_CASE("(SD) stat returns correct values", "[fatfs][ignore]")
106+
TEST_CASE("(SD) stat returns correct values", "[fatfs][test_env=UT_T1_SDMODE]")
107107
{
108108
test_setup();
109109
test_fatfs_stat("/sdcard/stat.txt", "/sdcard");
110110
test_teardown();
111111
}
112112

113-
TEST_CASE("(SD) unlink removes a file", "[fatfs][ignore]")
113+
TEST_CASE("(SD) unlink removes a file", "[fatfs][test_env=UT_T1_SDMODE]")
114114
{
115115
test_setup();
116116
test_fatfs_unlink("/sdcard/unlink.txt");
117117
test_teardown();
118118
}
119119

120-
TEST_CASE("(SD) link copies a file, rename moves a file", "[fatfs][ignore]")
120+
TEST_CASE("(SD) link copies a file, rename moves a file", "[fatfs][test_env=UT_T1_SDMODE]")
121121
{
122122
test_setup();
123123
test_fatfs_link_rename("/sdcard/link");
124124
test_teardown();
125125
}
126126

127-
TEST_CASE("(SD) can create and remove directories", "[fatfs][ignore]")
127+
TEST_CASE("(SD) can create and remove directories", "[fatfs][test_env=UT_T1_SDMODE]")
128128
{
129129
test_setup();
130130
test_fatfs_mkdir_rmdir("/sdcard/dir");
131131
test_teardown();
132132
}
133133

134-
TEST_CASE("(SD) can opendir root directory of FS", "[fatfs][ignore]")
134+
TEST_CASE("(SD) can opendir root directory of FS", "[fatfs][test_env=UT_T1_SDMODE]")
135135
{
136136
test_setup();
137137
test_fatfs_can_opendir("/sdcard");
138138
test_teardown();
139139
}
140140

141-
TEST_CASE("(SD) opendir, readdir, rewinddir, seekdir work as expected", "[fatfs][ignore]")
141+
TEST_CASE("(SD) opendir, readdir, rewinddir, seekdir work as expected", "[fatfs][test_env=UT_T1_SDMODE]")
142142
{
143143
test_setup();
144144
test_fatfs_opendir_readdir_rewinddir("/sdcard/dir");
145145
test_teardown();
146146
}
147147

148-
TEST_CASE("(SD) multiple tasks can use same volume", "[fatfs][ignore]")
148+
TEST_CASE("(SD) multiple tasks can use same volume", "[fatfs][test_env=UT_T1_SDMODE]")
149149
{
150150
test_setup();
151151
test_fatfs_concurrent("/sdcard/f");
@@ -154,7 +154,7 @@ TEST_CASE("(SD) multiple tasks can use same volume", "[fatfs][ignore]")
154154

155155
static void speed_test(void* buf, size_t buf_size, size_t file_size, bool write);
156156

157-
TEST_CASE("(SD) write/read speed test", "[fatfs][sdcard][ignore]")
157+
TEST_CASE("(SD) write/read speed test", "[fatfs][sd][test_env=UT_T1_SDMODE]")
158158
{
159159
size_t heap_size;
160160
HEAP_SIZE_CAPTURE(heap_size);
@@ -164,7 +164,7 @@ TEST_CASE("(SD) write/read speed test", "[fatfs][sdcard][ignore]")
164164
for (size_t i = 0; i < buf_size / 4; ++i) {
165165
buf[i] = esp_random();
166166
}
167-
const size_t file_size = 4 * 1024 * 1024;
167+
const size_t file_size = 1 * 1024 * 1024;
168168

169169
speed_test(buf, 4 * 1024, file_size, true);
170170
speed_test(buf, 8 * 1024, file_size, true);
@@ -196,7 +196,7 @@ static void speed_test(void* buf, size_t buf_size, size_t file_size, bool write)
196196
TEST_ESP_OK(esp_vfs_fat_sdmmc_unmount());
197197
}
198198

199-
TEST_CASE("(SD) mount two FAT partitions, SDMMC and WL, at the same time", "[fatfs][sdcard][ignore]")
199+
TEST_CASE("(SD) mount two FAT partitions, SDMMC and WL, at the same time", "[fatfs][sd][test_env=UT_T1_SDMODE]")
200200
{
201201
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
202202
.format_if_mount_failed = true,
@@ -247,7 +247,10 @@ TEST_CASE("(SD) mount two FAT partitions, SDMMC and WL, at the same time", "[fat
247247
* Ensure that the text editor is UTF-8 compatible when compiling these tests.
248248
*/
249249
#if defined(CONFIG_FATFS_API_ENCODING_UTF_8) && (CONFIG_FATFS_CODEPAGE == 936)
250-
TEST_CASE("(SD) can read file using UTF-8 encoded strings", "[fatfs][ignore]")
250+
251+
static const char* test_filename_utf_8 = "/sdcard/测试文件.txt";
252+
253+
TEST_CASE("(SD) can read file using UTF-8 encoded strings", "[fatfs][sd][test_env=UT_T1_SDMODE]")
251254
{
252255
test_setup();
253256
test_fatfs_create_file_with_text(test_filename_utf_8, fatfs_test_hello_str_utf);
@@ -261,4 +264,4 @@ TEST_CASE("(SD) opendir, readdir, rewinddir, seekdir work as expected using UTF-
261264
test_fatfs_opendir_readdir_rewinddir_utf_8("/sdcard/目录");
262265
test_teardown();
263266
}
264-
#endif
267+
#endif // CONFIG_FATFS_API_ENCODING_UTF_8 && CONFIG_FATFS_CODEPAGE == 936

components/sdmmc/sdmmc_cmd.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,9 @@ esp_err_t sdmmc_card_init(const sdmmc_host_t* config, sdmmc_card_t* card)
112112
ESP_LOGD(TAG, "SDHC/SDXC card");
113113
host_ocr |= SD_OCR_SDHC_CAP;
114114
} else if (err == ESP_ERR_TIMEOUT) {
115-
ESP_LOGD(TAG, "CMD8 timeout; not an SDHC/SDXC card");
115+
ESP_LOGD(TAG, "CMD8 timeout; not an SD v2.00 card");
116+
} else if (is_spi && err == ESP_ERR_NOT_SUPPORTED) {
117+
ESP_LOGD(TAG, "CMD8 rejected; not an SD v2.00 card");
116118
} else {
117119
ESP_LOGE(TAG, "%s: send_if_cond (1) returned 0x%x", __func__, err);
118120
return err;

0 commit comments

Comments
 (0)