Merge branch 'feat/esp32s3_essl_sdmmc_host' into 'master'

essl: add support for ESP32-S3 SDMMC host

See merge request espressif/esp-idf!19325
This commit is contained in:
Michael (XIAO Xufeng)
2022-11-22 11:18:32 +08:00
9 changed files with 173 additions and 104 deletions

View File

@@ -16,7 +16,6 @@
#include "driver/sdspi_host.h" #include "driver/sdspi_host.h"
#include "soc/soc_caps.h" #include "soc/soc_caps.h"
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3)
#if SOC_SDMMC_HOST_SUPPORTED && SOC_SDIO_SLAVE_SUPPORTED #if SOC_SDMMC_HOST_SUPPORTED && SOC_SDIO_SLAVE_SUPPORTED
#include "soc/sdio_slave_pins.h" #include "soc/sdio_slave_pins.h"
@@ -810,5 +809,3 @@ ptest_func_t tohost_slave = {
TEST_MASTER_SLAVE(SDIO_TOHOST, test_cfg_array, "[sdio][timeout=180][test_env=sdio_master_slave]", &tohost_master, &tohost_slave); TEST_MASTER_SLAVE(SDIO_TOHOST, test_cfg_array, "[sdio][timeout=180][test_env=sdio_master_slave]", &tohost_master, &tohost_slave);
#endif //SOC_SDMMC_HOST_SUPPORTED && SOC_SDIO_SLAVE_SUPPORTED #endif //SOC_SDMMC_HOST_SUPPORTED && SOC_SDIO_SLAVE_SUPPORTED
#endif

View File

@@ -1,38 +0,0 @@
// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _SOC_SDMMC_PINS_H_
#define _SOC_SDMMC_PINS_H_
#define SDMMC_SLOT0_IOMUX_PIN_NUM_CLK 12
#define SDMMC_SLOT0_IOMUX_PIN_NUM_CMD 11
#define SDMMC_SLOT0_IOMUX_PIN_NUM_D0 13
#define SDMMC_SLOT0_IOMUX_PIN_NUM_D1 14
#define SDMMC_SLOT0_IOMUX_PIN_NUM_D2 9
#define SDMMC_SLOT0_IOMUX_PIN_NUM_D3 10
#define SDMMC_SLOT0_IOMUX_PIN_NUM_D4 16
#define SDMMC_SLOT0_IOMUX_PIN_NUM_D5 17
#define SDMMC_SLOT0_IOMUX_PIN_NUM_D6 5
#define SDMMC_SLOT0_IOMUX_PIN_NUM_D7 18
#define SDMMC_SLOT0_FUNC 0
#define SDMMC_SLOT1_IOMUX_PIN_NUM_CLK 36
#define SDMMC_SLOT1_IOMUX_PIN_NUM_CMD 35
#define SDMMC_SLOT1_IOMUX_PIN_NUM_D0 37
#define SDMMC_SLOT1_IOMUX_PIN_NUM_D1 38
#define SDMMC_SLOT1_IOMUX_PIN_NUM_D2 33
#define SDMMC_SLOT1_IOMUX_PIN_NUM_D3 34
#define SDMMC_SLOT1_FUNC 3
#endif /* _SOC_SDMMC_PINS_H_ */

View File

@@ -150,7 +150,14 @@ examples/peripherals/rmt/stepper_motor:
disable: disable:
- if: SOC_RMT_SUPPORT_TX_LOOP_AUTO_STOP != 1 - if: SOC_RMT_SUPPORT_TX_LOOP_AUTO_STOP != 1
examples/peripherals/sdio: examples/peripherals/sdio/host:
enable:
- if: SOC_SDMMC_HOST_SUPPORTED == 1
- if: IDF_TARGET == "esp32"
temporary: true
reason: Only the SDSPI of ESP32 supports ESP SDIO slave for now
examples/peripherals/sdio/slave:
disable: disable:
- if: SOC_SDIO_SLAVE_SUPPORTED != 1 - if: SOC_SDIO_SLAVE_SUPPORTED != 1

View File

@@ -1,6 +1,3 @@
| Supported Targets | ESP32 |
| ----------------- | ----- |
### SDIO Example ### SDIO Example
## Introduction ## Introduction
@@ -25,8 +22,11 @@ is required if 4-bit mode is used. DAT3 is required in 4-bit mode (connected
to host), or required by the slave as mode detect in 1-bit mode (pull up). It to host), or required by the slave as mode detect in 1-bit mode (pull up). It
is okay in 1-bit mode to leave DAT3 of host disconnected. is okay in 1-bit mode to leave DAT3 of host disconnected.
Please run wires between the slave and master to make the example function Please run wires between the slave and master to make the example function, and don't forget the grounding wires.
(pins are the same for the host and the slave):
### Slave
On ESP32, the pins of SDIO Slave are fixed:
| Signal | GPIO NUM | | Signal | GPIO NUM |
|--------|----------| |--------|----------|
@@ -36,30 +36,39 @@ Please run wires between the slave and master to make the example function
| DAT1 | GPIO-4 | | DAT1 | GPIO-4 |
| DAT2 | GPIO-12 | | DAT2 | GPIO-12 |
| DAT3 | GPIO-13 | | DAT3 | GPIO-13 |
| Ground | GND |
CMD and DAT0-3 lines require to be pulled up by 50KOhm resistors even in Be aware that these pins are normally reserved for JTAG on ESP32. If you're
1-bit mode. See *Board Compability* below for details. In 1-bit mode, the
host can make use of DAT2 and DAT3, however the slave should leave them alone
but pulled up.
Be aware that the example uses lines normally reserved for JTAG. If you're
using a board with JTAG functions, please remember to remove jumpers using a board with JTAG functions, please remember to remove jumpers
connecting to the JTAG adapter. The SD peripheral works at a high frequency connecting to the JTAG adapter. The SD peripheral works at a high frequency
and uses native pins, there's no way to configure it to other pins through and uses native pins, there's no way to configure it to other pins through
the GPIO matrix. the GPIO matrix.
Please make sure CMD and DATA lines are pulled up by 50KOhm resistors even in ### Host
1-bit mode or SPI mode, which is required by the SD specification.
On ESP32, the pins of the SDMMC Host are fixed (same as the SDIO slave, see above).
When using SPI Master as the host, or using SDMMC Host on ESP32-S3, the pins are flexible. There are Kconfig options to
select all 6 pins to communicate with the slave. Even if the pins are not used (for example D2 in SPI mode) or
disconnected, the config options are still valid, and the host example will still initialize all the pins to help the
slave meet the "all pins should be pulled up" requirement.
For the SDIO Slave, CMD and DAT0-3 lines require to be pulled up (suggested resistor value: 10 KOhm) even in 1-bit mode
or SPI mode, which is required by the SD specification. See *Board Compability* below for details.
In 1-bit mode, the host can make use of DAT2 and DAT3, however the slave should
leave them alone but pulled up.
The 4-bit mode can be configured in the menuconfig. If the 4-bit mode is not The 4-bit mode can be configured in the menuconfig. If the 4-bit mode is not
used, the host will not control the DAT3 line, the slave hardware is used, the host will not control the DAT3 line, the slave hardware is
responsible to pull-up the line (or the slave may run into the SPI mode and responsible to pull-up the line (or the slave may run into the SPI mode and
cause a crash). cause a crash).
The host uses HS mode by default. If the example does not work properly, The host uses HS mode by default. If the example does not work properly (especially when you see CRC error or timeout),
please try connecting two boards by short wires, grounding between two boards please try:
better or disabling the HS mode in menuconfig.
1. Connecting two boards by short wires
2. Grounding between two boards better (**Reliable grounding is very important for the example to work properly!**)
3. Disabling the HS mode in menuconfig
## Board compatibility ## Board compatibility

View File

@@ -0,0 +1,4 @@
| Supported Targets | ESP32 | ESP32-S3 |
| ----------------- | ----- | -------- |
See README.md in the parent folder

View File

@@ -1,11 +1,25 @@
menu "Example Configuration" menu "Example Configuration"
config EXAMPLE_SDIO_OVER_SPI orsource "$IDF_PATH/examples/common_components/env_caps/$IDF_TARGET/Kconfig.env_caps"
bool "Host use SPI bus to communicate with slave"
default n choice EXAMPLE_SDIO_INTERFACE
prompt "Interface to communicate with slave"
default EXAMPLE_SDIO_OVER_SDMMC
help help
If this is set, the host tries using SPI bus to communicate with slave. There are two interfaces to communicate with the SDIO slave: SDMMC and SPI.
Otherwise, the standarad SD bus is used. The SDMMC interface is 8 times faster than the SPI interface. However not all Espressif chips have this
interface.
Alternatively you can use the SPI interface.
config EXAMPLE_SDIO_OVER_SDMMC
bool "SDMMC host"
depends on SOC_SDMMC_HOST_SUPPORTED
config EXAMPLE_SDIO_OVER_SPI
bool "SPI"
depends on IDF_TARGET_ESP32
endchoice
config EXAMPLE_SDIO_4BIT config EXAMPLE_SDIO_4BIT
bool "Host tries using 4-bit mode to communicate with slave" bool "Host tries using 4-bit mode to communicate with slave"
@@ -24,6 +38,7 @@ menu "Example Configuration"
config EXAMPLE_SDIO_HIGHSPEED config EXAMPLE_SDIO_HIGHSPEED
bool "Host tries using HS mode to communicate with slave" bool "Host tries using HS mode to communicate with slave"
default y default y
depends on EXAMPLE_SDIO_OVER_SDMMC
help help
If this is set, the host tries using high-speed mode to communicate If this is set, the host tries using high-speed mode to communicate
with slave. If the slave doesn't support high-speed mode, the with slave. If the slave doesn't support high-speed mode, the
@@ -32,16 +47,45 @@ menu "Example Configuration"
If the example does not work, please try disabling the HS mode. If the example does not work, please try disabling the HS mode.
config EXAMPLE_NO_INTR_LINE config EXAMPLE_ADJUSTABLE_PIN
bool "The host is not connected to the interrupt line (DAT1) of slave" bool
default n default EXAMPLE_SDIO_OVER_SPI || SOC_SDMMC_USE_GPIO_MATRIX
help
If this is set, the host example will not check the interrupt line but poll slave
registers to see whether the slave has interrupts for the host.
Working without the interrupt line may increase the CPU load of the host, and do harm config EXAMPLE_PIN_CMD
to the response speed to slave events, though can save 1 GPIO for other purposes in int "CMD (MOSI) GPIO number"
non-4-bit mode. depends on EXAMPLE_ADJUSTABLE_PIN
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
default 15
config EXAMPLE_PIN_CLK
int "CLK GPIO number"
depends on EXAMPLE_ADJUSTABLE_PIN
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
default 14
config EXAMPLE_PIN_D0
int "D0 (MISO) GPIO number"
depends on EXAMPLE_ADJUSTABLE_PIN
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
default 2
config EXAMPLE_PIN_D1
int "D1 (INTR) GPIO number"
depends on EXAMPLE_ADJUSTABLE_PIN
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
default 4
config EXAMPLE_PIN_D2
int "D2 GPIO number"
depends on EXAMPLE_ADJUSTABLE_PIN
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
default 12
config EXAMPLE_PIN_D3
int "D3 (CS) GPIO number"
depends on EXAMPLE_ADJUSTABLE_PIN
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
default 13
choice EXAMPLE_SLAVE choice EXAMPLE_SLAVE
prompt "GPIO to control slave EN in Espressif master-slave board." prompt "GPIO to control slave EN in Espressif master-slave board."
@@ -62,4 +106,15 @@ menu "Example Configuration"
help help
Slave power control pin is negtive active, otherwise postive active Slave power control pin is negtive active, otherwise postive active
config EXAMPLE_NO_INTR_LINE
bool "The host is not connected to the interrupt line (DAT1) of slave"
default n
help
If this is set, the host example will not check the interrupt line but poll slave
registers to see whether the slave has interrupts for the host.
Working without the interrupt line may increase the CPU load of the host, and do harm
to the response speed to slave events, though can save 1 GPIO for other purposes in
non-4-bit mode.
endmenu endmenu

View File

@@ -11,32 +11,51 @@
#include <stddef.h> #include <stddef.h>
#include <string.h> #include <string.h>
#include <inttypes.h> #include <inttypes.h>
#include "soc/soc_caps.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "freertos/semphr.h" #include "freertos/semphr.h"
#include "freertos/queue.h" #include "freertos/queue.h"
#include "soc/sdmmc_periph.h"
#include "soc/sdio_slave_periph.h"
#include "esp_log.h" #include "esp_log.h"
#include "esp_attr.h" #include "esp_attr.h"
#include "esp_serial_slave_link/essl_sdio.h"
#include "sdkconfig.h"
#include "driver/sdmmc_host.h" #include "driver/sdmmc_host.h"
#include "driver/sdspi_host.h" #include "driver/sdspi_host.h"
#include "esp_serial_slave_link/essl_sdio.h"
#include "sdkconfig.h"
#include "sdmmc_cmd.h" #include "sdmmc_cmd.h"
#define TIMEOUT_MAX UINT32_MAX #define TIMEOUT_MAX UINT32_MAX
#define GPIO_B1 21 #define GPIO_B1 21
#if CONFIG_EXAMPLE_SLAVE_B1 #if CONFIG_EXAMPLE_SLAVE_B1
#define SLAVE_PWR_GPIO GPIO_B1 #define SLAVE_PWR_GPIO GPIO_B1
#endif #endif
#if CONFIG_EXAMPLE_ADJUSTABLE_PIN
#define PIN_CLK CONFIG_EXAMPLE_PIN_CLK
#define PIN_CMD CONFIG_EXAMPLE_PIN_CMD
#define PIN_D0 CONFIG_EXAMPLE_PIN_D0
#define PIN_D1 CONFIG_EXAMPLE_PIN_D1
#define PIN_D2 CONFIG_EXAMPLE_PIN_D2
#define PIN_D3 CONFIG_EXAMPLE_PIN_D3
#else
// For ESP32 only, when not using SDMMC host
#include "soc/sdmmc_pins.h"
#define PIN_CLK SDMMC_SLOT1_IOMUX_PIN_NUM_CLK
#define PIN_CMD SDMMC_SLOT1_IOMUX_PIN_NUM_CMD
#define PIN_D0 SDMMC_SLOT1_IOMUX_PIN_NUM_D0
#define PIN_D1 SDMMC_SLOT1_IOMUX_PIN_NUM_D1
#define PIN_D2 SDMMC_SLOT1_IOMUX_PIN_NUM_D2
#define PIN_D3 SDMMC_SLOT1_IOMUX_PIN_NUM_D3
#endif
/* /*
sdio host example. sdio host example.
@@ -84,8 +103,6 @@
static const char TAG[] = "example_host"; static const char TAG[] = "example_host";
#define SDIO_INTERRUPT_LINE GPIO_NUM_4 //DATA1
#define SLAVE_INTR_NOTIFY 0 #define SLAVE_INTR_NOTIFY 0
#define SLAVE_REG_JOB 0 #define SLAVE_REG_JOB 0
@@ -122,12 +139,12 @@ esp_err_t slave_reset(essl_handle_t handle)
static void gpio_d2_set_high(void) static void gpio_d2_set_high(void)
{ {
gpio_config_t d2_config = { gpio_config_t d2_config = {
.pin_bit_mask = BIT64(SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_D2), .pin_bit_mask = BIT64(PIN_D2),
.mode = GPIO_MODE_OUTPUT, .mode = GPIO_MODE_OUTPUT,
.pull_up_en = true, .pull_up_en = true,
}; };
gpio_config(&d2_config); gpio_config(&d2_config);
gpio_set_level(SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_D2, 1); gpio_set_level(PIN_D2, 1);
} }
#endif #endif
@@ -190,6 +207,19 @@ esp_err_t slave_init(essl_handle_t* handle)
real design. real design.
*/ */
//slot_config.flags = SDMMC_SLOT_FLAG_INTERNAL_PULLUP; //slot_config.flags = SDMMC_SLOT_FLAG_INTERNAL_PULLUP;
//Initialize all pins to avoid them floating
//Set slot width to 4 to ignore other pin config on S3, which support at most 8 lines
slot_config.width = 4;
#ifdef CONFIG_SOC_SDMMC_USE_GPIO_MATRIX
slot_config.clk = PIN_CLK;
slot_config.cmd = PIN_CMD;
slot_config.d0 = PIN_D0;
slot_config.d1 = PIN_D1;
slot_config.d2 = PIN_D2;
slot_config.d3 = PIN_D3;
#endif // CONFIG_SOC_SDMMC_USE_GPIO_MATRIX
err = sdmmc_host_init(); err = sdmmc_host_init();
ESP_ERROR_CHECK(err); ESP_ERROR_CHECK(err);
@@ -197,27 +227,27 @@ esp_err_t slave_init(essl_handle_t* handle)
ESP_ERROR_CHECK(err); ESP_ERROR_CHECK(err);
#else //over SPI #else //over SPI
sdspi_device_config_t dev_config = SDSPI_DEVICE_CONFIG_DEFAULT(); sdspi_device_config_t dev_config = SDSPI_DEVICE_CONFIG_DEFAULT();
dev_config.gpio_cs = SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_D3; dev_config.gpio_cs = PIN_D3;
dev_config.gpio_int = SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_D1; dev_config.gpio_int = PIN_D1;
err = gpio_install_isr_service(0); err = gpio_install_isr_service(0);
ESP_ERROR_CHECK(err); ESP_ERROR_CHECK(err);
spi_bus_config_t bus_config = { spi_bus_config_t bus_config = {
.mosi_io_num = SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_CMD, .mosi_io_num = PIN_CMD,
.miso_io_num = SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_D0, .miso_io_num = PIN_D0,
.sclk_io_num = SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_CLK, .sclk_io_num = PIN_CLK,
.quadwp_io_num = -1, .quadwp_io_num = -1,
.quadhd_io_num = -1, .quadhd_io_num = -1,
.max_transfer_sz = 4000, .max_transfer_sz = 4000,
}; };
err = spi_bus_initialize(dev_config.host_id, &bus_config, 1); err = spi_bus_initialize(dev_config.host_id, &bus_config, SPI_DMA_CH_AUTO);
ESP_ERROR_CHECK(err); ESP_ERROR_CHECK(err);
sdspi_device_handle_t sdspi_handle; sdspi_dev_handle_t sdspi_handle;
err = sdspi_host_init(); err = sdspi_host_init();
ESP_ERROR_CHECK(err); ESP_ERROR_CHECK(err);
err = sdspi_host_init_device(&slot_config, &sdspi_handle); err = sdspi_host_init_device(&dev_config, &sdspi_handle);
ESP_ERROR_CHECK(err); ESP_ERROR_CHECK(err);
ESP_LOGI(TAG, "Probe using SPI...\n"); ESP_LOGI(TAG, "Probe using SPI...\n");
@@ -226,6 +256,7 @@ esp_err_t slave_init(essl_handle_t* handle)
//we have to pull up all the slave pins even when the pin is not used //we have to pull up all the slave pins even when the pin is not used
gpio_d2_set_high(); gpio_d2_set_high();
#endif //over SPI #endif //over SPI
sdmmc_card_t *card = (sdmmc_card_t *)malloc(sizeof(sdmmc_card_t)); sdmmc_card_t *card = (sdmmc_card_t *)malloc(sizeof(sdmmc_card_t));
if (card == NULL) { if (card == NULL) {
return ESP_ERR_NO_MEM; return ESP_ERR_NO_MEM;
@@ -239,18 +270,18 @@ esp_err_t slave_init(essl_handle_t* handle)
} }
sdmmc_card_print_info(stdout, card); sdmmc_card_print_info(stdout, card);
gpio_pullup_en(14); gpio_pullup_en(PIN_CMD);
gpio_pulldown_dis(14); gpio_pulldown_dis(PIN_CMD);
gpio_pullup_en(15); gpio_pullup_en(PIN_CLK);
gpio_pulldown_dis(15); gpio_pulldown_dis(PIN_CLK);
gpio_pullup_en(2); gpio_pullup_en(PIN_D0);
gpio_pulldown_dis(2); gpio_pulldown_dis(PIN_D0);
gpio_pullup_en(4); gpio_pullup_en(PIN_D1);
gpio_pulldown_dis(4); gpio_pulldown_dis(PIN_D1);
gpio_pullup_en(12); gpio_pullup_en(PIN_D2);
gpio_pulldown_dis(12); gpio_pulldown_dis(PIN_D2);
gpio_pullup_en(13); gpio_pullup_en(PIN_D3);
gpio_pulldown_dis(13); gpio_pulldown_dis(PIN_D3);
essl_sdio_config_t ser_config = { essl_sdio_config_t ser_config = {
.card = card, .card = card,
@@ -331,7 +362,7 @@ esp_err_t process_event(essl_handle_t handle)
} }
const int wait_ms = 50; const int wait_ms = 50;
if (intr_raw & HOST_SLC0_RX_NEW_PACKET_INT_ST) { if (intr_raw & ESSL_SDIO_DEF_ESP32.new_packet_intr_mask) {
ESP_LOGD(TAG, "new packet coming"); ESP_LOGD(TAG, "new packet coming");
while (1) { while (1) {
size_t size_read = READ_BUFFER_LEN; size_t size_read = READ_BUFFER_LEN;

View File

@@ -1,2 +1,2 @@
dependencies: dependencies:
espressif/esp_serial_slave_link: "^1.0.0" espressif/esp_serial_slave_link: "^1.0.1"

View File

@@ -0,0 +1,4 @@
| Supported Targets | ESP32 |
| ----------------- | ----- |
See README.md in the parent folder