Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sdcardio internal init_card_v2 maximum potential timeout is ridiculously long #9175

Open
hyx0329 opened this issue Apr 13, 2024 · 1 comment
Milestone

Comments

@hyx0329
Copy link

hyx0329 commented Apr 13, 2024

CircuitPython version

Adafruit CircuitPython 9.0.3(git tag), custom build for a RP2040 board

Code/REPL

import board
import sdcardio

bus = board.SPI()
# Run this, but do not connect the SD card's power
sd = sdcardio.SDCard(bus, board.SD_CS)

Behavior

No output, just stuck, for around 3 minutes

Description

No output, just stuck, for around 3 minutes. I think I found the cause, read more below. But I don't know how to improve it.

Additional information

In init_card_v2, the maximum potential timeout is given by CMD_TIMEOUT * (50ms + 3 cmd with wait), which is 200 * (50ms + 3 * 300ms) = 190 seconds. That's more than 3 minutes.

STATIC mp_rom_error_text_t init_card_v2(sdcardio_sdcard_obj_t *self) {
for (int i = 0; i < CMD_TIMEOUT; i++) {
uint8_t ocr[4];
common_hal_time_delay_ms(50);
cmd(self, 58, 0, ocr, sizeof(ocr), false, true);
cmd(self, 55, 0, NULL, 0, true, true);
if (cmd(self, 41, 0x40000000, NULL, 0, true, true) == 0) {
cmd(self, 58, 0, ocr, sizeof(ocr), false, true);
if ((ocr[0] & 0x40) != 0) {
self->cdv = 1;
}
return NULL;
}
}
return MP_ERROR_TEXT("timeout waiting for v2 card");
}

@hyx0329
Copy link
Author

hyx0329 commented Apr 14, 2024

Here's my current workaound

EDIT: I won't mind if someone just pick this and make a pr. But I doubt that having 2 types of time limits in a single function is appropriate.

diff --git a/shared-module/sdcardio/SDCard.c b/shared-module/sdcardio/SDCard.c
index 20c5afef0e..fc886964de 100644
--- a/shared-module/sdcardio/SDCard.c
+++ b/shared-module/sdcardio/SDCard.c
@@ -210,18 +210,26 @@ STATIC mp_rom_error_text_t init_card_v1(sdcardio_sdcard_obj_t *self) {
     return MP_ERROR_TEXT("timeout waiting for v1 card");
 }
 
+#define INIT_CARD_V2_ERROR_RETRY 5
 STATIC mp_rom_error_text_t init_card_v2(sdcardio_sdcard_obj_t *self) {
+    int early_error = 0;
     for (int i = 0; i < CMD_TIMEOUT; i++) {
         uint8_t ocr[4];
         common_hal_time_delay_ms(50);
-        cmd(self, 58, 0, ocr, sizeof(ocr), false, true);
-        cmd(self, 55, 0, NULL, 0, true, true);
-        if (cmd(self, 41, 0x40000000, NULL, 0, true, true) == 0) {
+        if (cmd(self, 58, 0, ocr, sizeof(ocr), false, true) >= 0
+            && cmd(self, 55, 0, NULL, 0, true, true) != -ETIMEDOUT
+            && cmd(self, 41, 0x40000000, NULL, 0, true, true) == 0) {
+
             cmd(self, 58, 0, ocr, sizeof(ocr), false, true);
             if ((ocr[0] & 0x40) != 0) {
                 self->cdv = 1;
             }
             return NULL;
+        } else {
+            early_error++;
+            if (early_error >= INIT_CARD_V2_ERROR_RETRY) {
+                break;
+            }
         }
     }
     return MP_ERROR_TEXT("timeout waiting for v2 card");

@dhalbert dhalbert added this to the 9.x.x milestone Apr 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants