mirror of
https://github.com/micropython/micropython.git
synced 2025-08-24 19:40:35 +02:00
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 <angus@redyak.com.au>
This commit is contained in:
committed by
Damien George
parent
4d65b4e261
commit
79fb5aa878
@@ -747,7 +747,7 @@ See :ref:`machine.SDCard <machine.SDCard>`. ::
|
||||
|
||||
import machine, os, vfs
|
||||
|
||||
# Slot 2 uses pins sck=18, cs=5, miso=19, mosi=23
|
||||
# On original ESP32, slot 2 uses pins sck=18, cs=5, miso=19, mosi=23
|
||||
sd = machine.SDCard(slot=2)
|
||||
vfs.mount(sd, '/sd') # mount
|
||||
|
||||
|
@@ -23,7 +23,8 @@ arguments that might need to be set in order to use either a non-standard slot
|
||||
or a non-standard pin assignment. The exact subset of arguments supported will
|
||||
vary from platform to platform.
|
||||
|
||||
.. class:: SDCard(slot=1, width=1, cd=None, wp=None, sck=None, miso=None, mosi=None, cs=None, freq=20000000)
|
||||
.. class:: SDCard(slot=1, width=1, cd=None, wp=None, sck=None, miso=None, mosi=None,
|
||||
cs=None, cmd=None, data=None, freq=20000000)
|
||||
|
||||
This class provides access to SD or MMC storage cards using either
|
||||
a dedicated SD/MMC interface hardware or through an SPI channel.
|
||||
@@ -37,7 +38,8 @@ vary from platform to platform.
|
||||
- *slot* selects which of the available interfaces to use. Leaving this
|
||||
unset will select the default interface.
|
||||
|
||||
- *width* selects the bus width for the SD/MMC interface.
|
||||
- *width* selects the bus width for the SD/MMC interface. This many data
|
||||
pins must be connected to the SD card.
|
||||
|
||||
- *cd* can be used to specify a card-detect pin.
|
||||
|
||||
@@ -51,7 +53,14 @@ vary from platform to platform.
|
||||
|
||||
- *cs* can be used to specify an SPI chip select pin.
|
||||
|
||||
- *freq* selects the SD/MMC interface frequency in Hz (only supported on the ESP32).
|
||||
The following additional parameters are only present on ESP32 port:
|
||||
|
||||
- *cmd* can be used to specify the SD CMD pin (ESP32-S3 only).
|
||||
|
||||
- *data* can be used to specify a list or tuple of SD data bus pins
|
||||
(ESP32-S3 only).
|
||||
|
||||
- *freq* selects the SD/MMC interface frequency in Hz.
|
||||
|
||||
Implementation-specific details
|
||||
-------------------------------
|
||||
@@ -67,52 +76,106 @@ The standard PyBoard has just one slot. No arguments are necessary or supported.
|
||||
ESP32
|
||||
`````
|
||||
|
||||
The ESP32 provides two channels of SD/MMC hardware and also supports
|
||||
access to SD Cards through either of the two SPI ports that are
|
||||
generally available to the user. As a result the *slot* argument can
|
||||
take a value between 0 and 3, inclusive. Slots 0 and 1 use the
|
||||
built-in SD/MMC hardware while slots 2 and 3 use the SPI ports. Slot 0
|
||||
supports 1, 4 or 8-bit wide access while slot 1 supports 1 or 4-bit
|
||||
access; the SPI slots only support 1-bit access.
|
||||
SD cards support access in both SD/MMC mode and the simpler (but slower) SPI
|
||||
mode. ESP32 and ESP32-S3 chips can access SD cards using either mode. SPI mode
|
||||
makes use of a `SPI` host peripheral, which cannot concurrently be used for
|
||||
something else.
|
||||
|
||||
.. note:: Slot 0 is used to communicate with on-board flash memory
|
||||
on most ESP32 modules and so will be unavailable to the
|
||||
user.
|
||||
The ``slot`` argument determines which mode is used. Different values are
|
||||
available on different chips:
|
||||
|
||||
.. note:: Most ESP32 modules that provide an SD card slot using the
|
||||
dedicated hardware only wire up 1 data pin, so the default
|
||||
value for *width* is 1.
|
||||
====== ================= ============ ========================
|
||||
Slot Supported chips Mode Supported data width
|
||||
====== ================= ============ ========================
|
||||
0 ESP32-S3 SD/MMC 1, 4, or 8 bits.
|
||||
1 ESP32, ESP32-S3 SD/MMC 1 or 4 bits.
|
||||
2 ESP32, ESP32-S3 `SPI` (id=1) 1 bit.
|
||||
3 ESP32, ESP32-S3 `SPI` (id=0) 1 bit.
|
||||
====== ================= ============ ========================
|
||||
|
||||
The pins used by the dedicated SD/MMC hardware are fixed. The pins
|
||||
used by the SPI hardware can be reassigned.
|
||||
.. note:: On the original ESP32, SDMMC slot 0 is unavailable as its pins are
|
||||
used to communicate with on-board flash memory.
|
||||
|
||||
.. note:: If any of the SPI signals are remapped then all of the SPI
|
||||
signals will pass through a GPIO multiplexer unit which
|
||||
can limit the performance of high frequency signals. Since
|
||||
the normal operating speed for SD cards is 40MHz this can
|
||||
cause problems on some cards.
|
||||
.. note:: Most ESP32 modules that provide an SD card slot using the
|
||||
dedicated hardware only wire up 1 data pin, so the default
|
||||
value for ``width`` is 1.
|
||||
|
||||
The default (and preferred) pin assignment are as follows:
|
||||
Additional details depend on which ESP32 family chip is in use:
|
||||
|
||||
====== ====== ====== ====== ======
|
||||
Slot 0 1 2 3
|
||||
------ ------ ------ ------ ------
|
||||
Signal Pin Pin Pin Pin
|
||||
====== ====== ====== ====== ======
|
||||
sck 6 14 18 14
|
||||
cmd 11 15
|
||||
cs 5 15
|
||||
miso 19 12
|
||||
mosi 23 13
|
||||
D0 7 2
|
||||
D1 8 4
|
||||
D2 9 12
|
||||
D3 10 13
|
||||
D4 16
|
||||
D5 17
|
||||
D6 5
|
||||
D7 18
|
||||
====== ====== ====== ====== ======
|
||||
Original ESP32
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
Pin assignments in SD/MMC mode are fixed on the original ESP32. When accessing a
|
||||
card in SPI mode, pins can be set to different values in the constructor.
|
||||
|
||||
The default pin assignments are as follows:
|
||||
|
||||
====== ====== ====== ====== ============
|
||||
Slot 1 2 3 Can be set
|
||||
------ ------ ------ ------ ------------
|
||||
Signal Pin Pin Pin
|
||||
====== ====== ====== ====== ============
|
||||
CLK 14 No
|
||||
CMD 15 No
|
||||
D0 2 No
|
||||
D1 4 No
|
||||
D2 12 No
|
||||
D3 13 No
|
||||
sck 18 14 Yes
|
||||
cs 5 15 Yes
|
||||
miso 19 12 Yes
|
||||
mosi 23 13 Yes
|
||||
====== ====== ====== ====== ============
|
||||
|
||||
The ``cd`` and ``wp`` pins are not fixed in either mode and default to disabled, unless set.
|
||||
|
||||
ESP32-S3
|
||||
~~~~~~~~
|
||||
|
||||
The ESP32-S3 chip allows pins to be set to different values for both SD/MMC and
|
||||
SPI mode access.
|
||||
|
||||
If not set, default pin assignments are as follows:
|
||||
|
||||
======== ====== ====== ====== ======
|
||||
Slot 0 1 2 3
|
||||
-------- ------ ------ ------ ------
|
||||
Signal Pin Pin Pin Pin
|
||||
======== ====== ====== ====== ======
|
||||
CLK 14 14
|
||||
CMD 15 15
|
||||
D0 2 2
|
||||
D1 4 4
|
||||
D2 12 12
|
||||
D3 13 13
|
||||
D4 33*
|
||||
D5 34*
|
||||
D6 35*
|
||||
D7 36*
|
||||
sck 37* 14
|
||||
cs 34* 13
|
||||
miso 37* 2
|
||||
mosi 35* 15
|
||||
======== ====== ====== ====== ======
|
||||
|
||||
.. note:: Slots 0 and 1 cannot both be in use at the same time.
|
||||
|
||||
.. note:: Pins marked with an asterisk * in the table must be changed from the
|
||||
default if the ESP32-S3 board is configured for Octal SPI Flash or
|
||||
PSRAM.
|
||||
|
||||
To access a card in SD/MMC mode, set ``slot`` parameter value 0 or 1 and
|
||||
parameters ``sck`` (for CLK), ``cmd`` and ``data`` as needed to assign pins. If
|
||||
the ``data`` argument is passed then it should be a list or tuple of data pins
|
||||
or pin numbers with length equal to the ``width`` argument. For example::
|
||||
|
||||
sd = SDCard(slot=0, width=4, sck=8, cmd=9, data=(10, 11, 12, 13))
|
||||
|
||||
To access a card in SPI mode, set ``slot`` parameter value 2 or 3 and pass
|
||||
parameters ``sck``, ``cs``, ``miso``, ``mosi`` as needed to assign pins.
|
||||
|
||||
In either mode the ``cd`` and ``wp`` pins default to disabled, unless set in the
|
||||
constructor.
|
||||
|
||||
cc3200
|
||||
``````
|
||||
|
@@ -177,6 +177,10 @@ static mp_obj_t machine_sdcard_make_new(const mp_obj_type_t *type, size_t n_args
|
||||
ARG_mosi,
|
||||
ARG_sck,
|
||||
ARG_cs,
|
||||
#if SOC_SDMMC_USE_GPIO_MATRIX
|
||||
ARG_cmd,
|
||||
ARG_data,
|
||||
#endif
|
||||
ARG_freq,
|
||||
};
|
||||
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
|
||||
{ MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_cs, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
// Optional assignment of SDMMC interface pins, if host supports this
|
||||
#if SOC_SDMMC_USE_GPIO_MATRIX
|
||||
{ MP_QSTR_cmd, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_data, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
#endif
|
||||
// freq is valid for both SPI and SDMMC interfaces
|
||||
{ MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 20000000} },
|
||||
};
|
||||
@@ -211,6 +220,11 @@ static mp_obj_t machine_sdcard_make_new(const mp_obj_type_t *type, size_t n_args
|
||||
arg_vals[ARG_miso].u_obj, arg_vals[ARG_mosi].u_obj,
|
||||
arg_vals[ARG_sck].u_obj, arg_vals[ARG_cs].u_obj);
|
||||
|
||||
#if SOC_SDMMC_USE_GPIO_MATRIX
|
||||
DEBUG_printf(" cmd=%p, data=%p",
|
||||
arg_vals[ARG_cmd].u_obj, arg_vals[ARG_data].u_obj);
|
||||
#endif
|
||||
|
||||
int slot_num = arg_vals[ARG_slot].u_int;
|
||||
if (slot_num < 0 || slot_num > 3) {
|
||||
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
|
||||
if (is_spi) {
|
||||
slot_num -= 2;
|
||||
}
|
||||
// Verify valid argument combinations
|
||||
#if SOC_SDMMC_USE_GPIO_MATRIX
|
||||
if (is_spi && (arg_vals[ARG_cmd].u_obj != mp_const_none
|
||||
|| arg_vals[ARG_data].u_obj != mp_const_none)) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("invalid config: SPI slot with SDMMC pin arguments"));
|
||||
}
|
||||
#endif
|
||||
|
||||
DEBUG_printf(" Setting up host configuration");
|
||||
|
||||
@@ -307,6 +328,32 @@ static mp_obj_t machine_sdcard_make_new(const mp_obj_type_t *type, size_t n_args
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("width must be 1 or 4 (or 8 on slot 0)"));
|
||||
}
|
||||
|
||||
#if SOC_SDMMC_USE_GPIO_MATRIX
|
||||
// Optionally configure all the SDMMC pins, if chip supports this
|
||||
SET_CONFIG_PIN(slot_config, clk, ARG_sck); // reuse SPI SCK for CLK
|
||||
SET_CONFIG_PIN(slot_config, cmd, ARG_cmd);
|
||||
if (arg_vals[ARG_data].u_obj != mp_const_none) {
|
||||
mp_obj_t *data_vals;
|
||||
size_t data_len;
|
||||
mp_obj_get_array(arg_vals[ARG_data].u_obj, &data_len, &data_vals);
|
||||
if (data_len != width) {
|
||||
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("data argument length must match width %d"), width);
|
||||
}
|
||||
slot_config.d0 = machine_pin_get_id(data_vals[0]);
|
||||
if (width > 1) {
|
||||
slot_config.d1 = machine_pin_get_id(data_vals[1]);
|
||||
slot_config.d2 = machine_pin_get_id(data_vals[2]);
|
||||
slot_config.d3 = machine_pin_get_id(data_vals[3]);
|
||||
}
|
||||
if (width == 8) {
|
||||
slot_config.d4 = machine_pin_get_id(data_vals[4]);
|
||||
slot_config.d5 = machine_pin_get_id(data_vals[5]);
|
||||
slot_config.d6 = machine_pin_get_id(data_vals[6]);
|
||||
slot_config.d7 = machine_pin_get_id(data_vals[7]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
DEBUG_printf(" Calling init_slot()");
|
||||
check_esp_err(sdmmc_host_init_slot(self->host.slot, &slot_config));
|
||||
}
|
||||
|
Reference in New Issue
Block a user