Skip to content

Commit 79fb5aa

Browse files
projectgusdpgeorge
authored andcommitted
esp32/machine_sdcard: Add SDCard pin assignments for ESP32-S3 support.
Previously ESP32-S3 SDMMC could only use fixed pin assignments, however the ESP-IDF defaults don't match common boards. The chip also supports using GPIO Matrix to assign any pin. This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton <[email protected]>
1 parent 4d65b4e commit 79fb5aa

File tree

3 files changed

+160
-50
lines changed

3 files changed

+160
-50
lines changed

docs/esp32/quickref.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -747,7 +747,7 @@ See :ref:`machine.SDCard <machine.SDCard>`. ::
747747

748748
import machine, os, vfs
749749

750-
# Slot 2 uses pins sck=18, cs=5, miso=19, mosi=23
750+
# On original ESP32, slot 2 uses pins sck=18, cs=5, miso=19, mosi=23
751751
sd = machine.SDCard(slot=2)
752752
vfs.mount(sd, '/sd') # mount
753753

docs/library/machine.SDCard.rst

Lines changed: 112 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ arguments that might need to be set in order to use either a non-standard slot
2323
or a non-standard pin assignment. The exact subset of arguments supported will
2424
vary from platform to platform.
2525

26-
.. class:: SDCard(slot=1, width=1, cd=None, wp=None, sck=None, miso=None, mosi=None, cs=None, freq=20000000)
26+
.. class:: SDCard(slot=1, width=1, cd=None, wp=None, sck=None, miso=None, mosi=None,
27+
cs=None, cmd=None, data=None, freq=20000000)
2728

2829
This class provides access to SD or MMC storage cards using either
2930
a dedicated SD/MMC interface hardware or through an SPI channel.
@@ -37,7 +38,8 @@ vary from platform to platform.
3738
- *slot* selects which of the available interfaces to use. Leaving this
3839
unset will select the default interface.
3940

40-
- *width* selects the bus width for the SD/MMC interface.
41+
- *width* selects the bus width for the SD/MMC interface. This many data
42+
pins must be connected to the SD card.
4143

4244
- *cd* can be used to specify a card-detect pin.
4345

@@ -51,7 +53,14 @@ vary from platform to platform.
5153

5254
- *cs* can be used to specify an SPI chip select pin.
5355

54-
- *freq* selects the SD/MMC interface frequency in Hz (only supported on the ESP32).
56+
The following additional parameters are only present on ESP32 port:
57+
58+
- *cmd* can be used to specify the SD CMD pin (ESP32-S3 only).
59+
60+
- *data* can be used to specify a list or tuple of SD data bus pins
61+
(ESP32-S3 only).
62+
63+
- *freq* selects the SD/MMC interface frequency in Hz.
5564

5665
Implementation-specific details
5766
-------------------------------
@@ -67,52 +76,106 @@ The standard PyBoard has just one slot. No arguments are necessary or supported.
6776
ESP32
6877
`````
6978

70-
The ESP32 provides two channels of SD/MMC hardware and also supports
71-
access to SD Cards through either of the two SPI ports that are
72-
generally available to the user. As a result the *slot* argument can
73-
take a value between 0 and 3, inclusive. Slots 0 and 1 use the
74-
built-in SD/MMC hardware while slots 2 and 3 use the SPI ports. Slot 0
75-
supports 1, 4 or 8-bit wide access while slot 1 supports 1 or 4-bit
76-
access; the SPI slots only support 1-bit access.
77-
78-
.. note:: Slot 0 is used to communicate with on-board flash memory
79-
on most ESP32 modules and so will be unavailable to the
80-
user.
81-
82-
.. note:: Most ESP32 modules that provide an SD card slot using the
83-
dedicated hardware only wire up 1 data pin, so the default
84-
value for *width* is 1.
85-
86-
The pins used by the dedicated SD/MMC hardware are fixed. The pins
87-
used by the SPI hardware can be reassigned.
88-
89-
.. note:: If any of the SPI signals are remapped then all of the SPI
90-
signals will pass through a GPIO multiplexer unit which
91-
can limit the performance of high frequency signals. Since
92-
the normal operating speed for SD cards is 40MHz this can
93-
cause problems on some cards.
94-
95-
The default (and preferred) pin assignment are as follows:
96-
97-
====== ====== ====== ====== ======
98-
Slot 0 1 2 3
99-
------ ------ ------ ------ ------
100-
Signal Pin Pin Pin Pin
101-
====== ====== ====== ====== ======
102-
sck 6 14 18 14
103-
cmd 11 15
104-
cs 5 15
105-
miso 19 12
106-
mosi 23 13
107-
D0 7 2
108-
D1 8 4
109-
D2 9 12
110-
D3 10 13
111-
D4 16
112-
D5 17
113-
D6 5
114-
D7 18
115-
====== ====== ====== ====== ======
79+
SD cards support access in both SD/MMC mode and the simpler (but slower) SPI
80+
mode. ESP32 and ESP32-S3 chips can access SD cards using either mode. SPI mode
81+
makes use of a `SPI` host peripheral, which cannot concurrently be used for
82+
something else.
83+
84+
The ``slot`` argument determines which mode is used. Different values are
85+
available on different chips:
86+
87+
====== ================= ============ ========================
88+
Slot Supported chips Mode Supported data width
89+
====== ================= ============ ========================
90+
0 ESP32-S3 SD/MMC 1, 4, or 8 bits.
91+
1 ESP32, ESP32-S3 SD/MMC 1 or 4 bits.
92+
2 ESP32, ESP32-S3 `SPI` (id=1) 1 bit.
93+
3 ESP32, ESP32-S3 `SPI` (id=0) 1 bit.
94+
====== ================= ============ ========================
95+
96+
.. note:: On the original ESP32, SDMMC slot 0 is unavailable as its pins are
97+
used to communicate with on-board flash memory.
98+
99+
.. note:: Most ESP32 modules that provide an SD card slot using the
100+
dedicated hardware only wire up 1 data pin, so the default
101+
value for ``width`` is 1.
102+
103+
Additional details depend on which ESP32 family chip is in use:
104+
105+
Original ESP32
106+
~~~~~~~~~~~~~~
107+
108+
Pin assignments in SD/MMC mode are fixed on the original ESP32. When accessing a
109+
card in SPI mode, pins can be set to different values in the constructor.
110+
111+
The default pin assignments are as follows:
112+
113+
====== ====== ====== ====== ============
114+
Slot 1 2 3 Can be set
115+
------ ------ ------ ------ ------------
116+
Signal Pin Pin Pin
117+
====== ====== ====== ====== ============
118+
CLK 14 No
119+
CMD 15 No
120+
D0 2 No
121+
D1 4 No
122+
D2 12 No
123+
D3 13 No
124+
sck 18 14 Yes
125+
cs 5 15 Yes
126+
miso 19 12 Yes
127+
mosi 23 13 Yes
128+
====== ====== ====== ====== ============
129+
130+
The ``cd`` and ``wp`` pins are not fixed in either mode and default to disabled, unless set.
131+
132+
ESP32-S3
133+
~~~~~~~~
134+
135+
The ESP32-S3 chip allows pins to be set to different values for both SD/MMC and
136+
SPI mode access.
137+
138+
If not set, default pin assignments are as follows:
139+
140+
======== ====== ====== ====== ======
141+
Slot 0 1 2 3
142+
-------- ------ ------ ------ ------
143+
Signal Pin Pin Pin Pin
144+
======== ====== ====== ====== ======
145+
CLK 14 14
146+
CMD 15 15
147+
D0 2 2
148+
D1 4 4
149+
D2 12 12
150+
D3 13 13
151+
D4 33*
152+
D5 34*
153+
D6 35*
154+
D7 36*
155+
sck 37* 14
156+
cs 34* 13
157+
miso 37* 2
158+
mosi 35* 15
159+
======== ====== ====== ====== ======
160+
161+
.. note:: Slots 0 and 1 cannot both be in use at the same time.
162+
163+
.. note:: Pins marked with an asterisk * in the table must be changed from the
164+
default if the ESP32-S3 board is configured for Octal SPI Flash or
165+
PSRAM.
166+
167+
To access a card in SD/MMC mode, set ``slot`` parameter value 0 or 1 and
168+
parameters ``sck`` (for CLK), ``cmd`` and ``data`` as needed to assign pins. If
169+
the ``data`` argument is passed then it should be a list or tuple of data pins
170+
or pin numbers with length equal to the ``width`` argument. For example::
171+
172+
sd = SDCard(slot=0, width=4, sck=8, cmd=9, data=(10, 11, 12, 13))
173+
174+
To access a card in SPI mode, set ``slot`` parameter value 2 or 3 and pass
175+
parameters ``sck``, ``cs``, ``miso``, ``mosi`` as needed to assign pins.
176+
177+
In either mode the ``cd`` and ``wp`` pins default to disabled, unless set in the
178+
constructor.
116179

117180
cc3200
118181
``````

ports/esp32/machine_sdcard.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,10 @@ static mp_obj_t machine_sdcard_make_new(const mp_obj_type_t *type, size_t n_args
177177
ARG_mosi,
178178
ARG_sck,
179179
ARG_cs,
180+
#if SOC_SDMMC_USE_GPIO_MATRIX
181+
ARG_cmd,
182+
ARG_data,
183+
#endif
180184
ARG_freq,
181185
};
182186
static const mp_arg_t allowed_args[] = {
@@ -189,6 +193,11 @@ static mp_obj_t machine_sdcard_make_new(const mp_obj_type_t *type, size_t n_args
189193
{ MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
190194
{ MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
191195
{ MP_QSTR_cs, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
196+
// Optional assignment of SDMMC interface pins, if host supports this
197+
#if SOC_SDMMC_USE_GPIO_MATRIX
198+
{ MP_QSTR_cmd, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
199+
{ MP_QSTR_data, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
200+
#endif
192201
// freq is valid for both SPI and SDMMC interfaces
193202
{ MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 20000000} },
194203
};
@@ -211,6 +220,11 @@ static mp_obj_t machine_sdcard_make_new(const mp_obj_type_t *type, size_t n_args
211220
arg_vals[ARG_miso].u_obj, arg_vals[ARG_mosi].u_obj,
212221
arg_vals[ARG_sck].u_obj, arg_vals[ARG_cs].u_obj);
213222

223+
#if SOC_SDMMC_USE_GPIO_MATRIX
224+
DEBUG_printf(" cmd=%p, data=%p",
225+
arg_vals[ARG_cmd].u_obj, arg_vals[ARG_data].u_obj);
226+
#endif
227+
214228
int slot_num = arg_vals[ARG_slot].u_int;
215229
if (slot_num < 0 || slot_num > 3) {
216230
mp_raise_ValueError(MP_ERROR_TEXT("slot number must be between 0 and 3 inclusive"));
@@ -221,6 +235,13 @@ static mp_obj_t machine_sdcard_make_new(const mp_obj_type_t *type, size_t n_args
221235
if (is_spi) {
222236
slot_num -= 2;
223237
}
238+
// Verify valid argument combinations
239+
#if SOC_SDMMC_USE_GPIO_MATRIX
240+
if (is_spi && (arg_vals[ARG_cmd].u_obj != mp_const_none
241+
|| arg_vals[ARG_data].u_obj != mp_const_none)) {
242+
mp_raise_ValueError(MP_ERROR_TEXT("invalid config: SPI slot with SDMMC pin arguments"));
243+
}
244+
#endif
224245

225246
DEBUG_printf(" Setting up host configuration");
226247

@@ -307,6 +328,32 @@ static mp_obj_t machine_sdcard_make_new(const mp_obj_type_t *type, size_t n_args
307328
mp_raise_ValueError(MP_ERROR_TEXT("width must be 1 or 4 (or 8 on slot 0)"));
308329
}
309330

331+
#if SOC_SDMMC_USE_GPIO_MATRIX
332+
// Optionally configure all the SDMMC pins, if chip supports this
333+
SET_CONFIG_PIN(slot_config, clk, ARG_sck); // reuse SPI SCK for CLK
334+
SET_CONFIG_PIN(slot_config, cmd, ARG_cmd);
335+
if (arg_vals[ARG_data].u_obj != mp_const_none) {
336+
mp_obj_t *data_vals;
337+
size_t data_len;
338+
mp_obj_get_array(arg_vals[ARG_data].u_obj, &data_len, &data_vals);
339+
if (data_len != width) {
340+
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("data argument length must match width %d"), width);
341+
}
342+
slot_config.d0 = machine_pin_get_id(data_vals[0]);
343+
if (width > 1) {
344+
slot_config.d1 = machine_pin_get_id(data_vals[1]);
345+
slot_config.d2 = machine_pin_get_id(data_vals[2]);
346+
slot_config.d3 = machine_pin_get_id(data_vals[3]);
347+
}
348+
if (width == 8) {
349+
slot_config.d4 = machine_pin_get_id(data_vals[4]);
350+
slot_config.d5 = machine_pin_get_id(data_vals[5]);
351+
slot_config.d6 = machine_pin_get_id(data_vals[6]);
352+
slot_config.d7 = machine_pin_get_id(data_vals[7]);
353+
}
354+
}
355+
#endif
356+
310357
DEBUG_printf(" Calling init_slot()");
311358
check_esp_err(sdmmc_host_init_slot(self->host.slot, &slot_config));
312359
}

0 commit comments

Comments
 (0)