Skip to content

Commit 236dec0

Browse files
committed
shorten SDCard SPI timeouts, which were freezing out ESP32SPI access; remove RUN_BACKGROUND_TASKS in SDCard
1 parent d455dff commit 236dec0

File tree

3 files changed

+19
-22
lines changed

3 files changed

+19
-22
lines changed

ports/espressif/boards/adafruit_metro_esp32s3/mpconfigboard.mk

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,3 @@ CIRCUITPY_ESP_FLASH_SIZE = 16MB
1212
CIRCUITPY_ESP_PSRAM_MODE = opi
1313
CIRCUITPY_ESP_PSRAM_FREQ = 80m
1414
CIRCUITPY_ESP_PSRAM_SIZE = 8MB
15-
16-
CIRCUITPY_ULAB = 0

shared-bindings/busio/SPI.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818
#include "shared-bindings/util.h"
1919
#include "shared/runtime/buffer_helper.h"
2020
#include "shared/runtime/context_manager_helpers.h"
21+
#include "shared/runtime/interrupt_char.h"
2122
#include "supervisor/shared/tick.h"
2223

23-
2424
//| class SPI:
2525
//| """A 3-4 wire serial protocol
2626
//|
@@ -499,7 +499,8 @@ busio_spi_obj_t *validate_obj_is_spi_bus(mp_obj_t obj, qstr arg_name) {
499499
// The default implementation is to busy-wait while running the background tasks. espressif is different.
500500
bool common_hal_busio_spi_wait_for_lock(busio_spi_obj_t *self, uint32_t timeout_ms) {
501501
uint64_t deadline = supervisor_ticks_ms64() + timeout_ms;
502-
while (supervisor_ticks_ms64() < deadline) {
502+
while (supervisor_ticks_ms64() < deadline &&
503+
!mp_hal_is_interrupted()) {
503504
if (common_hal_busio_spi_try_lock(self)) {
504505
return true;
505506
}

shared-module/sdcardio/SDCard.c

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,24 @@
1616
#include "supervisor/shared/tick.h"
1717

1818
#include "py/mperrno.h"
19+
#include "py/mphal.h"
1920

2021
#if 0
2122
#define DEBUG_PRINT(...) ((void)mp_printf(&mp_plat_print,##__VA_ARGS__))
2223
#else
2324
#define DEBUG_PRINT(...) ((void)0)
2425
#endif
2526

27+
// https://nodeloop.org/guides/sd-card-spi-init-guide/ is an excellent source of info for SPI card use.
28+
2629
// https://www.taterli.com/wp-content/uploads/2017/05/Physical-Layer-Simplified-SpecificationV6.0.pdf
2730
// specifies timeouts for read (100 ms), write (250 ms), erase (depends on size), and other operations.
2831
// But the document also suggests allowing 500 ms even if a shorter timeout is specified.
29-
// So let's allow a nice long time, but don't wait in a tight loop: allow background tasks to run.
30-
#define CMD_TIMEOUT_MS (500)
31-
#define TIMEOUT_MS (500)
32-
#define SPI_TIMEOUT_MS (10000)
32+
#define CMD_TIMEOUT_MS (250)
33+
#define SPI_TIMEOUT_MS (250)
34+
// Init ready timeout.
35+
#define READY_TIMEOUT_MS (300)
36+
3337

3438
#define R1_IDLE_STATE (1 << 0)
3539
#define R1_ILLEGAL_COMMAND (1 << 2)
@@ -84,11 +88,10 @@ static void lock_bus_or_throw(sdcardio_sdcard_obj_t *self) {
8488
}
8589

8690
static void clock_card(sdcardio_sdcard_obj_t *self, int bytes) {
87-
uint8_t buf[] = {0xff};
91+
uint8_t buf[bytes];
92+
memset(buf, 0xff, bytes);
8893
common_hal_digitalio_digitalinout_set_value(&self->cs, true);
89-
for (int i = 0; i < bytes; i++) {
90-
common_hal_busio_spi_write(self->bus, buf, 1);
91-
}
94+
common_hal_busio_spi_write(self->bus, buf, bytes);
9295
}
9396

9497
static void extraclock_and_unlock_bus(sdcardio_sdcard_obj_t *self) {
@@ -124,19 +127,16 @@ static int32_t wait_for_masked_response(sdcardio_sdcard_obj_t *self, uint8_t mas
124127
if (((b & mask) == response) ^ not_match) {
125128
return b;
126129
}
127-
RUN_BACKGROUND_TASKS;
128130
}
129131
return -1;
130132
}
131133

132134
// Wait for the given response byte.
133135
static bool wait_for_response(sdcardio_sdcard_obj_t *self, uint8_t response) {
134-
return wait_for_masked_response(self, 0xff, response, false, TIMEOUT_MS) != -1;
136+
return wait_for_masked_response(self, 0xff, response, false, CMD_TIMEOUT_MS) != -1;
135137
}
136138

137-
#define READY_TIMEOUT_MS (300)
138-
139-
// Wait for 0xff, with a shorter timeout.
139+
// Wait for 0xff, with a specific timeout.
140140
static bool wait_for_ready(sdcardio_sdcard_obj_t *self) {
141141
return wait_for_masked_response(self, 0xff, 0xff, false, READY_TIMEOUT_MS) != -1;
142142
}
@@ -232,7 +232,6 @@ static mp_rom_error_text_t init_card_v1(sdcardio_sdcard_obj_t *self) {
232232
if (cmd(self, 41, 0, NULL, 0, true, true) == 0) {
233233
return NULL;
234234
}
235-
RUN_BACKGROUND_TASKS;
236235
}
237236
return MP_ERROR_TEXT("timeout waiting for v1 card");
238237
}
@@ -251,12 +250,13 @@ static mp_rom_error_text_t init_card_v2(sdcardio_sdcard_obj_t *self) {
251250
}
252251
return NULL;
253252
}
254-
RUN_BACKGROUND_TASKS;
255253
}
256254
return MP_ERROR_TEXT("timeout waiting for v2 card");
257255
}
258256

259257
static mp_rom_error_text_t init_card(sdcardio_sdcard_obj_t *self) {
258+
// https://nodeloop.org/guides/sd-card-spi-init-guide/ recommends at least 74 bit clocks
259+
// and says 80 bit clocks(10*8) is common. Value below is bytes, not bits.
260260
clock_card(self, 10);
261261

262262
common_hal_digitalio_digitalinout_set_value(&self->cs, false);
@@ -476,21 +476,19 @@ static int _write(sdcardio_sdcard_obj_t *self, uint8_t token, void *buf, size_t
476476
uint64_t deadline = supervisor_ticks_ms64() + CMD_TIMEOUT_MS;
477477
while (supervisor_ticks_ms64() < deadline) {
478478
common_hal_busio_spi_read(self->bus, cmd, 1, 0xff);
479-
DEBUG_PRINT("i=%02d cmd[0] = 0x%02x\n", i, cmd[0]);
480479
if ((cmd[0] & 0b00010001) == 0b00000001) {
481480
if ((cmd[0] & 0x1f) != 0x5) {
482481
return -MP_EIO;
483482
} else {
484483
break;
485484
}
486485
}
487-
RUN_BACKGROUND_TASKS;
488486
}
489487

490488
// Wait for the write to finish
491489

492490
// Wait for a non-zero value.
493-
if (wait_for_masked_response(self, 0xff /*mask*/, 0, true /*not_match*/, TIMEOUT_MS) == -1) {
491+
if (wait_for_masked_response(self, 0xff /*mask*/, 0, true /*not_match*/, CMD_TIMEOUT_MS) == -1) {
494492
return -MP_EIO;
495493
}
496494

0 commit comments

Comments
 (0)