example/sdio: add support for ESP32-S3 as host (via SD)

This commit is contained in:
Michael (XIAO Xufeng) 2022-08-01 19:46:52 +08:00
parent 96b0cb2828
commit 720b86a886
8 changed files with 173 additions and 66 deletions

View File

@ -16,7 +16,6 @@
#include "driver/sdspi_host.h"
#include "soc/soc_caps.h"
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3)
#if SOC_SDMMC_HOST_SUPPORTED && SOC_SDIO_SLAVE_SUPPORTED
#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);
#endif //SOC_SDMMC_HOST_SUPPORTED && SOC_SDIO_SLAVE_SUPPORTED
#endif

View File

@ -150,7 +150,14 @@ examples/peripherals/rmt/stepper_motor:
disable:
- 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:
- if: SOC_SDIO_SLAVE_SUPPORTED != 1

View File

@ -1,6 +1,3 @@
| Supported Targets | ESP32 |
| ----------------- | ----- |
### SDIO Example
## 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
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
(pins are the same for the host and the slave):
Please run wires between the slave and master to make the example function, and don't forget the grounding wires.
### Slave
On ESP32, the pins of SDIO Slave are fixed:
| Signal | GPIO NUM |
|--------|----------|
@ -36,30 +36,39 @@ Please run wires between the slave and master to make the example function
| DAT1 | GPIO-4 |
| DAT2 | GPIO-12 |
| DAT3 | GPIO-13 |
| Ground | GND |
CMD and DAT0-3 lines require to be pulled up by 50KOhm resistors even in
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
Be aware that these pins are normally reserved for JTAG on ESP32. If you're
using a board with JTAG functions, please remember to remove jumpers
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
the GPIO matrix.
Please make sure CMD and DATA lines are pulled up by 50KOhm resistors even in
1-bit mode or SPI mode, which is required by the SD specification.
### Host
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
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
cause a crash).
The host uses HS mode by default. If the example does not work properly,
please try connecting two boards by short wires, grounding between two boards
better or disabling the HS mode in menuconfig.
The host uses HS mode by default. If the example does not work properly (especially when you see CRC error or timeout),
please try:
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

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"
config EXAMPLE_SDIO_OVER_SPI
bool "Host use SPI bus to communicate with slave"
default n
orsource "$IDF_PATH/examples/common_components/env_caps/$IDF_TARGET/Kconfig.env_caps"
choice EXAMPLE_SDIO_INTERFACE
prompt "Interface to communicate with slave"
default EXAMPLE_SDIO_OVER_SDMMC
help
If this is set, the host tries using SPI bus to communicate with slave.
Otherwise, the standarad SD bus is used.
There are two interfaces to communicate with the SDIO slave: SDMMC and SPI.
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
bool "Host tries using 4-bit mode to communicate with slave"
@ -24,6 +38,7 @@ menu "Example Configuration"
config EXAMPLE_SDIO_HIGHSPEED
bool "Host tries using HS mode to communicate with slave"
default y
depends on EXAMPLE_SDIO_OVER_SDMMC
help
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
@ -32,16 +47,45 @@ menu "Example Configuration"
If the example does not work, please try disabling the HS mode.
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.
config EXAMPLE_ADJUSTABLE_PIN
bool
default EXAMPLE_SDIO_OVER_SPI || SOC_SDMMC_USE_GPIO_MATRIX
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.
config EXAMPLE_PIN_CMD
int "CMD (MOSI) GPIO number"
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
prompt "GPIO to control slave EN in Espressif master-slave board."
@ -62,4 +106,15 @@ menu "Example Configuration"
help
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

View File

@ -11,32 +11,51 @@
#include <stddef.h>
#include <string.h>
#include <inttypes.h>
#include "soc/soc_caps.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"
#include "soc/sdmmc_periph.h"
#include "soc/sdio_slave_periph.h"
#include "esp_log.h"
#include "esp_attr.h"
#include "esp_serial_slave_link/essl_sdio.h"
#include "sdkconfig.h"
#include "driver/sdmmc_host.h"
#include "driver/sdspi_host.h"
#include "esp_serial_slave_link/essl_sdio.h"
#include "sdkconfig.h"
#include "sdmmc_cmd.h"
#define TIMEOUT_MAX UINT32_MAX
#define GPIO_B1 21
#if CONFIG_EXAMPLE_SLAVE_B1
#define SLAVE_PWR_GPIO GPIO_B1
#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.
@ -84,8 +103,6 @@
static const char TAG[] = "example_host";
#define SDIO_INTERRUPT_LINE GPIO_NUM_4 //DATA1
#define SLAVE_INTR_NOTIFY 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)
{
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,
.pull_up_en = true,
};
gpio_config(&d2_config);
gpio_set_level(SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_D2, 1);
gpio_set_level(PIN_D2, 1);
}
#endif
@ -190,6 +207,19 @@ esp_err_t slave_init(essl_handle_t* handle)
real design.
*/
//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();
ESP_ERROR_CHECK(err);
@ -197,27 +227,27 @@ esp_err_t slave_init(essl_handle_t* handle)
ESP_ERROR_CHECK(err);
#else //over SPI
sdspi_device_config_t dev_config = SDSPI_DEVICE_CONFIG_DEFAULT();
dev_config.gpio_cs = SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_D3;
dev_config.gpio_int = SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_D1;
dev_config.gpio_cs = PIN_D3;
dev_config.gpio_int = PIN_D1;
err = gpio_install_isr_service(0);
ESP_ERROR_CHECK(err);
spi_bus_config_t bus_config = {
.mosi_io_num = SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_CMD,
.miso_io_num = SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_D0,
.sclk_io_num = SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_CLK,
.mosi_io_num = PIN_CMD,
.miso_io_num = PIN_D0,
.sclk_io_num = PIN_CLK,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.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);
sdspi_device_handle_t sdspi_handle;
sdspi_dev_handle_t sdspi_handle;
err = sdspi_host_init();
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_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
gpio_d2_set_high();
#endif //over SPI
sdmmc_card_t *card = (sdmmc_card_t *)malloc(sizeof(sdmmc_card_t));
if (card == NULL) {
return ESP_ERR_NO_MEM;
@ -239,18 +270,18 @@ esp_err_t slave_init(essl_handle_t* handle)
}
sdmmc_card_print_info(stdout, card);
gpio_pullup_en(14);
gpio_pulldown_dis(14);
gpio_pullup_en(15);
gpio_pulldown_dis(15);
gpio_pullup_en(2);
gpio_pulldown_dis(2);
gpio_pullup_en(4);
gpio_pulldown_dis(4);
gpio_pullup_en(12);
gpio_pulldown_dis(12);
gpio_pullup_en(13);
gpio_pulldown_dis(13);
gpio_pullup_en(PIN_CMD);
gpio_pulldown_dis(PIN_CMD);
gpio_pullup_en(PIN_CLK);
gpio_pulldown_dis(PIN_CLK);
gpio_pullup_en(PIN_D0);
gpio_pulldown_dis(PIN_D0);
gpio_pullup_en(PIN_D1);
gpio_pulldown_dis(PIN_D1);
gpio_pullup_en(PIN_D2);
gpio_pulldown_dis(PIN_D2);
gpio_pullup_en(PIN_D3);
gpio_pulldown_dis(PIN_D3);
essl_sdio_config_t ser_config = {
.card = card,
@ -331,7 +362,7 @@ esp_err_t process_event(essl_handle_t handle)
}
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");
while (1) {
size_t size_read = READ_BUFFER_LEN;

View File

@ -1,2 +1,2 @@
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