mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feat/sdio_pullup' into 'master'
feature(sdio): add features to make SDIO slave compatible with more devkits See merge request idf/esp-idf!2454
This commit is contained in:
commit
4b91c82cc4
@ -20,7 +20,7 @@
|
||||
#include "esp_err.h"
|
||||
#include "rom/queue.h"
|
||||
|
||||
#include "soc/host_reg.h"
|
||||
#include "soc/sdio_slave_periph.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -71,6 +71,23 @@ typedef struct {
|
||||
///< All data that do not fully fill a buffer is still counted as one buffer. E.g. 10 bytes data costs 2 buffers if the size is 8 bytes per buffer.
|
||||
///< Buffer size of the slave pre-defined between host and slave before communication. All receive buffer given to the driver should be larger than this.
|
||||
sdio_event_cb_t event_cb; ///< when the host interrupts slave, this callback will be called with interrupt number (0-7).
|
||||
uint32_t flags; ///< Features to be enabled for the slave, combinations of ``SDIO_SLAVE_FLAG_*``.
|
||||
#define SDIO_SLAVE_FLAG_DAT2_DISABLED BIT(0) /**< It is required by the SD specification that all 4 data
|
||||
lines should be used and pulled up even in 1-bit mode or SPI mode. However, as a feature, the user can speicfy
|
||||
this flag to make use of DAT2 pin in 1-bit mode. Note that the host cannot read CCCR registers to know we don't
|
||||
support 4-bit mode anymore, please do this at your own risk.
|
||||
*/
|
||||
#define SDIO_SLAVE_FLAG_HOST_INTR_DISABLED BIT(1) /**< The DAT1 line is used as the interrupt line in SDIO
|
||||
protocol. However, as a feature, the user can speicfy this flag to make use of DAT1 pin of the slave in 1-bit
|
||||
mode. Note that the host has to do polling to the interrupt registers to know whether there are interrupts from
|
||||
the slave. And it cannot read CCCR registers to know we don't support 4-bit mode anymore, please do this at
|
||||
your own risk.
|
||||
*/
|
||||
#define SDIO_SLAVE_FLAG_INTERNAL_PULLUP BIT(2) /**< Enable internal pullups for enabled pins. It is required
|
||||
by the SD specification that all the 4 data lines should be pulled up even in 1-bit mode or SPI mode. Note that
|
||||
the internal pull-ups are not sufficient for stable communication, please do connect external pull-ups on the
|
||||
bus. This is only for example and debug use.
|
||||
*/
|
||||
} sdio_slave_config_t;
|
||||
|
||||
/** Handle of a receive buffer, register a handle by calling ``sdio_slave_recv_register_buf``. Use the handle to load the buffer to the
|
||||
|
@ -55,6 +55,12 @@ typedef struct {
|
||||
gpio_num_t gpio_cd; ///< GPIO number of card detect signal
|
||||
gpio_num_t gpio_wp; ///< GPIO number of write protect signal
|
||||
uint8_t width; ///< Bus width used by the slot (might be less than the max width supported)
|
||||
uint32_t flags; ///< Features used by this slot
|
||||
#define SDMMC_SLOT_FLAG_INTERNAL_PULLUP BIT(0)
|
||||
/**< Enable internal pullups on enabled pins. The internal pullups
|
||||
are insufficient however, please make sure external pullups are
|
||||
connected on the bus. This is for debug / example purpose only.
|
||||
*/
|
||||
} sdmmc_slot_config_t;
|
||||
|
||||
#define SDMMC_SLOT_NO_CD ((gpio_num_t) -1) ///< indicates that card detect line is not used
|
||||
@ -68,6 +74,7 @@ typedef struct {
|
||||
.gpio_cd = SDMMC_SLOT_NO_CD, \
|
||||
.gpio_wp = SDMMC_SLOT_NO_WP, \
|
||||
.width = SDMMC_SLOT_WIDTH_DEFAULT, \
|
||||
.flags = 0, \
|
||||
}
|
||||
|
||||
/**
|
||||
@ -199,6 +206,23 @@ esp_err_t sdmmc_host_io_int_wait(int slot, TickType_t timeout_ticks);
|
||||
*/
|
||||
esp_err_t sdmmc_host_deinit();
|
||||
|
||||
/**
|
||||
* @brief Enable the pull-ups of sd pins.
|
||||
*
|
||||
* @note You should always place actual pullups on the lines instead of using
|
||||
* this function. Internal pullup resistance are high and not sufficient, may
|
||||
* cause instability in products. This is for debug or examples only.
|
||||
*
|
||||
* @param slot Slot to use, normally set it to 1.
|
||||
* @param width Bit width of your configuration, 1 or 4.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: if success
|
||||
* - ESP_ERR_INVALID_ARG: if configured width larger than maximum the slot can
|
||||
* support
|
||||
*/
|
||||
esp_err_t sdmmc_host_pullup_en(int slot, int width);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -86,10 +86,7 @@ The driver of FIFOs works as below:
|
||||
|
||||
#include <string.h>
|
||||
#include "driver/sdio_slave.h"
|
||||
#include "soc/slc_struct.h"
|
||||
#include "soc/slc_reg.h"
|
||||
#include "soc/host_struct.h"
|
||||
#include "soc/hinf_struct.h"
|
||||
#include "soc/sdio_slave_periph.h"
|
||||
#include "rom/lldesc.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
@ -119,41 +116,6 @@ typedef enum {
|
||||
STATE_SENDING = 3,
|
||||
} send_state_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t clk;
|
||||
uint32_t cmd;
|
||||
uint32_t d0;
|
||||
uint32_t d1;
|
||||
uint32_t d2;
|
||||
uint32_t d3;
|
||||
int func;
|
||||
} sdio_slave_slot_info_t ;
|
||||
|
||||
// I/O slot of sdio slave:
|
||||
// 0: GPIO 6, 11, 7, 8, 9, 10,
|
||||
// 1: GPIO 14, 15, 2, 4, 12, 13 for CLK, CMD, D0, D1, D2, D3 respectively.
|
||||
// only one peripheral for SDIO and only one slot can work at the same time.
|
||||
// currently slot 0 is occupied by SPI for flash
|
||||
static const sdio_slave_slot_info_t s_slot_info[2] = {
|
||||
{
|
||||
.clk = PERIPHS_IO_MUX_SD_CLK_U,
|
||||
.cmd = PERIPHS_IO_MUX_SD_CMD_U,
|
||||
.d0 = PERIPHS_IO_MUX_SD_DATA0_U,
|
||||
.d1 = PERIPHS_IO_MUX_SD_DATA1_U,
|
||||
.d2 = PERIPHS_IO_MUX_SD_DATA2_U,
|
||||
.d3 = PERIPHS_IO_MUX_SD_DATA3_U,
|
||||
.func = 0,
|
||||
}, {
|
||||
.clk = PERIPHS_IO_MUX_MTMS_U,
|
||||
.cmd = PERIPHS_IO_MUX_MTDO_U,
|
||||
.d0 = PERIPHS_IO_MUX_GPIO2_U,
|
||||
.d1 = PERIPHS_IO_MUX_GPIO4_U,
|
||||
.d2 = PERIPHS_IO_MUX_MTDI_U,
|
||||
.d3 = PERIPHS_IO_MUX_MTCK_U,
|
||||
.func = 4,
|
||||
},
|
||||
};
|
||||
|
||||
// first 3 WORDs of this struct is defined by and compatible to the DMA link list format.
|
||||
// sdio_slave_buf_handle_t is of type buf_desc_t*;
|
||||
typedef struct buf_desc_s{
|
||||
@ -225,7 +187,7 @@ typedef struct {
|
||||
/*------- receiving ---------------*/
|
||||
buf_stailq_t recv_link_list; // now ready to/already hold data
|
||||
buf_tailq_t recv_reg_list; // removed from the link list, registered but not used now
|
||||
buf_desc_t* recv_cur_ret;
|
||||
volatile buf_desc_t* recv_cur_ret; // next desc to return, NULL if all loaded descriptors are returned
|
||||
portMUX_TYPE recv_spinlock;
|
||||
} sdio_context_t;
|
||||
|
||||
@ -499,13 +461,21 @@ no_mem:
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
static inline void configure_pin(uint32_t io_mux_reg, uint32_t func)
|
||||
static void configure_pin(int pin, uint32_t func, bool pullup)
|
||||
{
|
||||
const int sdmmc_func = func;
|
||||
const int drive_strength = 3;
|
||||
PIN_INPUT_ENABLE(io_mux_reg);
|
||||
PIN_FUNC_SELECT(io_mux_reg, sdmmc_func);
|
||||
PIN_SET_DRV(io_mux_reg, drive_strength);
|
||||
assert(pin!=-1);
|
||||
uint32_t reg = GPIO_PIN_MUX_REG[pin];
|
||||
assert(reg!=UINT32_MAX);
|
||||
|
||||
PIN_INPUT_ENABLE(reg);
|
||||
PIN_FUNC_SELECT(reg, sdmmc_func);
|
||||
PIN_SET_DRV(reg, drive_strength);
|
||||
if (pullup) {
|
||||
gpio_pullup_en(pin);
|
||||
gpio_pulldown_dis(pin);
|
||||
}
|
||||
}
|
||||
|
||||
static inline esp_err_t sdio_slave_hw_init(sdio_slave_config_t *config)
|
||||
@ -514,13 +484,20 @@ static inline esp_err_t sdio_slave_hw_init(sdio_slave_config_t *config)
|
||||
SLC.slc0_int_ena.val = 0;
|
||||
|
||||
//initialize pin
|
||||
const sdio_slave_slot_info_t *slot = &s_slot_info[1];
|
||||
configure_pin(slot->clk, slot->func);
|
||||
configure_pin(slot->cmd, slot->func);
|
||||
configure_pin(slot->d0, slot->func);
|
||||
configure_pin(slot->d1, slot->func);
|
||||
configure_pin(slot->d2, slot->func);
|
||||
configure_pin(slot->d3, slot->func);
|
||||
const sdio_slave_slot_info_t *slot = &sdio_slave_slot_info[1];
|
||||
|
||||
bool pullup = config->flags & SDIO_SLAVE_FLAG_INTERNAL_PULLUP;
|
||||
configure_pin(slot->clk_gpio, slot->func, false); //clk doesn't need a pullup
|
||||
configure_pin(slot->cmd_gpio, slot->func, pullup);
|
||||
configure_pin(slot->d0_gpio, slot->func, pullup);
|
||||
if ((config->flags & SDIO_SLAVE_FLAG_HOST_INTR_DISABLED)==0) {
|
||||
configure_pin(slot->d1_gpio, slot->func, pullup);
|
||||
}
|
||||
if ((config->flags & SDIO_SLAVE_FLAG_DAT2_DISABLED)==0) {
|
||||
configure_pin(slot->d2_gpio, slot->func, pullup);
|
||||
}
|
||||
configure_pin(slot->d3_gpio, slot->func, pullup);
|
||||
|
||||
//enable module and config
|
||||
periph_module_reset(PERIPH_SDIO_SLAVE_MODULE);
|
||||
periph_module_enable(PERIPH_SDIO_SLAVE_MODULE);
|
||||
@ -1160,8 +1137,6 @@ static void sdio_intr_recv(void* arg)
|
||||
portBASE_TYPE yield = 0;
|
||||
if ( SLC.slc0_int_raw.tx_done ) {
|
||||
SLC.slc0_int_clr.tx_done = 1;
|
||||
assert( context.recv_cur_ret != NULL );
|
||||
|
||||
while ( context.recv_cur_ret && context.recv_cur_ret->owner == 0 ) {
|
||||
// This may cause the ``cur_ret`` pointer to be NULL, indicating the list is empty,
|
||||
// in this case the ``tx_done`` should happen no longer until new desc is appended.
|
||||
@ -1186,15 +1161,24 @@ esp_err_t sdio_slave_recv_load_buf(sdio_slave_buf_handle_t handle)
|
||||
desc->owner = 1;
|
||||
desc->not_receiving = 0; //manually remove the prev link (by set not_receiving=0), to indicate this is in the queue
|
||||
|
||||
// 1. If all desc are returned in the ISR, the pointer is moved to NULL. The pointer is set to the newly appended desc here.
|
||||
// 2. If the pointer is move to some not-returned desc (maybe the one appended here), do nothing.
|
||||
// The ``cur_ret`` pointer must be checked and set after new desc appended to the list, or the pointer setting may fail.
|
||||
buf_desc_t *const tail = STAILQ_LAST(queue, buf_desc_s, qe);
|
||||
|
||||
STAILQ_INSERT_TAIL( queue, desc, qe );
|
||||
if ( context.recv_cur_ret == NULL ) {
|
||||
if (tail == NULL || (tail->owner == 0)) {
|
||||
//in this case we have to set the ret pointer
|
||||
if (tail != NULL) {
|
||||
/* if the owner of the tail is returned to the software, the ISR is
|
||||
* expect to write this pointer to NULL in a short time, wait until
|
||||
* that and set new value for this pointer
|
||||
*/
|
||||
while (context.recv_cur_ret != NULL) {}
|
||||
}
|
||||
assert(context.recv_cur_ret == NULL);
|
||||
context.recv_cur_ret = desc;
|
||||
}
|
||||
assert(context.recv_cur_ret != NULL);
|
||||
|
||||
if ( desc == STAILQ_FIRST(queue) ) {
|
||||
if (tail == NULL) {
|
||||
//no one in the ll, start new ll operation.
|
||||
SLC.slc0_tx_link.addr = (uint32_t)desc;
|
||||
SLC.slc0_tx_link.start = 1;
|
||||
|
@ -17,76 +17,21 @@
|
||||
#include <sys/param.h>
|
||||
#include "esp_log.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "soc/sdmmc_struct.h"
|
||||
#include "soc/sdmmc_reg.h"
|
||||
#include "soc/io_mux_reg.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
#include "rom/gpio.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/sdmmc_host.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
#include "sdmmc_private.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "soc/sdmmc_periph.h"
|
||||
|
||||
#define SDMMC_EVENT_QUEUE_LENGTH 32
|
||||
|
||||
typedef struct {
|
||||
uint32_t clk;
|
||||
uint32_t cmd;
|
||||
uint32_t d0;
|
||||
uint32_t d1;
|
||||
uint32_t d2;
|
||||
uint32_t d3;
|
||||
uint32_t d4;
|
||||
uint32_t d5;
|
||||
uint32_t d6;
|
||||
uint32_t d7;
|
||||
uint8_t d1_gpio;
|
||||
uint8_t d3_gpio;
|
||||
uint8_t card_detect;
|
||||
uint8_t write_protect;
|
||||
uint8_t card_int;
|
||||
uint8_t width;
|
||||
} sdmmc_slot_info_t;
|
||||
|
||||
|
||||
static void sdmmc_isr(void* arg);
|
||||
static void sdmmc_host_dma_init();
|
||||
|
||||
static const sdmmc_slot_info_t s_slot_info[2] = {
|
||||
{
|
||||
.clk = PERIPHS_IO_MUX_SD_CLK_U,
|
||||
.cmd = PERIPHS_IO_MUX_SD_CMD_U,
|
||||
.d0 = PERIPHS_IO_MUX_SD_DATA0_U,
|
||||
.d1 = PERIPHS_IO_MUX_SD_DATA1_U,
|
||||
.d2 = PERIPHS_IO_MUX_SD_DATA2_U,
|
||||
.d3 = PERIPHS_IO_MUX_SD_DATA3_U,
|
||||
.d1_gpio = 8,
|
||||
.d3_gpio = 10,
|
||||
.d4 = PERIPHS_IO_MUX_GPIO16_U,
|
||||
.d5 = PERIPHS_IO_MUX_GPIO17_U,
|
||||
.d6 = PERIPHS_IO_MUX_GPIO5_U,
|
||||
.d7 = PERIPHS_IO_MUX_GPIO18_U,
|
||||
.card_detect = HOST_CARD_DETECT_N_1_IDX,
|
||||
.write_protect = HOST_CARD_WRITE_PRT_1_IDX,
|
||||
.card_int = HOST_CARD_INT_N_1_IDX,
|
||||
.width = 8
|
||||
},
|
||||
{
|
||||
.clk = PERIPHS_IO_MUX_MTMS_U,
|
||||
.cmd = PERIPHS_IO_MUX_MTDO_U,
|
||||
.d0 = PERIPHS_IO_MUX_GPIO2_U,
|
||||
.d1 = PERIPHS_IO_MUX_GPIO4_U,
|
||||
.d2 = PERIPHS_IO_MUX_MTDI_U,
|
||||
.d3 = PERIPHS_IO_MUX_MTCK_U,
|
||||
.d1_gpio = 4,
|
||||
.d3_gpio = 13,
|
||||
.card_detect = HOST_CARD_DETECT_N_2_IDX,
|
||||
.write_protect = HOST_CARD_WRITE_PRT_2_IDX,
|
||||
.card_int = HOST_CARD_INT_N_2_IDX,
|
||||
.width = 4
|
||||
}
|
||||
};
|
||||
|
||||
static const char* TAG = "sdmmc_periph";
|
||||
static intr_handle_t s_intr_handle;
|
||||
@ -340,18 +285,24 @@ esp_err_t sdmmc_host_init()
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
static inline void configure_pin(uint32_t io_mux_reg)
|
||||
static void configure_pin(int pin)
|
||||
{
|
||||
const int sdmmc_func = 3;
|
||||
const int drive_strength = 3;
|
||||
PIN_INPUT_ENABLE(io_mux_reg);
|
||||
PIN_FUNC_SELECT(io_mux_reg, sdmmc_func);
|
||||
PIN_SET_DRV(io_mux_reg, drive_strength);
|
||||
assert(pin!=-1);
|
||||
uint32_t reg = GPIO_PIN_MUX_REG[pin];
|
||||
assert(reg != UINT32_MAX);
|
||||
PIN_INPUT_ENABLE(reg);
|
||||
PIN_FUNC_SELECT(reg, sdmmc_func);
|
||||
PIN_SET_DRV(reg, drive_strength);
|
||||
}
|
||||
|
||||
esp_err_t sdmmc_host_init_slot(int slot, const sdmmc_slot_config_t* slot_config)
|
||||
{
|
||||
bool pullup = slot_config->flags & SDMMC_SLOT_FLAG_INTERNAL_PULLUP;
|
||||
if (pullup) {
|
||||
sdmmc_host_pullup_en(slot, slot_config->width);
|
||||
}
|
||||
if (!s_intr_handle) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
@ -366,7 +317,7 @@ esp_err_t sdmmc_host_init_slot(int slot, const sdmmc_slot_config_t* slot_config)
|
||||
uint8_t slot_width = slot_config->width;
|
||||
|
||||
// Configure pins
|
||||
const sdmmc_slot_info_t* pslot = &s_slot_info[slot];
|
||||
const sdmmc_slot_info_t* pslot = &sdmmc_slot_info[slot];
|
||||
|
||||
if (slot_width == SDMMC_SLOT_WIDTH_DEFAULT) {
|
||||
slot_width = pslot->width;
|
||||
@ -376,13 +327,13 @@ esp_err_t sdmmc_host_init_slot(int slot, const sdmmc_slot_config_t* slot_config)
|
||||
}
|
||||
s_slot_width[slot] = slot_width;
|
||||
|
||||
configure_pin(pslot->clk);
|
||||
configure_pin(pslot->cmd);
|
||||
configure_pin(pslot->d0);
|
||||
configure_pin(pslot->clk_gpio);
|
||||
configure_pin(pslot->cmd_gpio);
|
||||
configure_pin(pslot->d0_gpio);
|
||||
|
||||
if (slot_width >= 4) {
|
||||
configure_pin(pslot->d1);
|
||||
configure_pin(pslot->d2);
|
||||
configure_pin(pslot->d1_gpio);
|
||||
configure_pin(pslot->d2_gpio);
|
||||
//force pull-up D3 to make slave detect SD mode. connect to peripheral after width configuration.
|
||||
gpio_config_t gpio_conf = {
|
||||
.pin_bit_mask = BIT(pslot->d3_gpio),
|
||||
@ -394,10 +345,10 @@ esp_err_t sdmmc_host_init_slot(int slot, const sdmmc_slot_config_t* slot_config)
|
||||
gpio_config( &gpio_conf );
|
||||
gpio_set_level( pslot->d3_gpio, 1 );
|
||||
if (slot_width == 8) {
|
||||
configure_pin(pslot->d4);
|
||||
configure_pin(pslot->d5);
|
||||
configure_pin(pslot->d6);
|
||||
configure_pin(pslot->d7);
|
||||
configure_pin(pslot->d4_gpio);
|
||||
configure_pin(pslot->d5_gpio);
|
||||
configure_pin(pslot->d6_gpio);
|
||||
configure_pin(pslot->d7_gpio);
|
||||
}
|
||||
}
|
||||
|
||||
@ -482,7 +433,7 @@ esp_err_t sdmmc_host_set_bus_width(int slot, size_t width)
|
||||
if (!(slot == 0 || slot == 1)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (s_slot_info[slot].width < width) {
|
||||
if (sdmmc_slot_info[slot].width < width) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
const uint16_t mask = BIT(slot);
|
||||
@ -492,10 +443,10 @@ esp_err_t sdmmc_host_set_bus_width(int slot, size_t width)
|
||||
} else if (width == 4) {
|
||||
SDMMC.ctype.card_width_8 &= ~mask;
|
||||
SDMMC.ctype.card_width |= mask;
|
||||
configure_pin(s_slot_info[slot].d3); // D3 was set to GPIO high to force slave into SD 1-bit mode, until 4-bit mode is set
|
||||
configure_pin(sdmmc_slot_info[slot].d3_gpio); // D3 was set to GPIO high to force slave into SD 1-bit mode, until 4-bit mode is set
|
||||
} else if (width == 8){
|
||||
SDMMC.ctype.card_width_8 |= mask;
|
||||
configure_pin(s_slot_info[slot].d3); // D3 was set to GPIO high to force slave into SD 1-bit mode, until 4-bit mode is set
|
||||
configure_pin(sdmmc_slot_info[slot].d3_gpio); // D3 was set to GPIO high to force slave into SD 1-bit mode, until 4-bit mode is set
|
||||
} else {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
@ -550,7 +501,7 @@ void sdmmc_host_dma_resume()
|
||||
|
||||
esp_err_t sdmmc_host_io_int_enable(int slot)
|
||||
{
|
||||
configure_pin(s_slot_info[slot].d1);
|
||||
configure_pin(sdmmc_slot_info[slot].d1_gpio);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -566,7 +517,7 @@ esp_err_t sdmmc_host_io_int_wait(int slot, TickType_t timeout_ticks)
|
||||
|
||||
SDMMC.intmask.sdio &= ~BIT(slot); /* Disable SDIO interrupt */
|
||||
SDMMC.rintsts.sdio = BIT(slot);
|
||||
if (gpio_get_level(s_slot_info[slot].d1_gpio) == 0) {
|
||||
if (gpio_get_level(sdmmc_slot_info[slot].d1_gpio) == 0) {
|
||||
return ESP_OK;
|
||||
}
|
||||
/* Otherwise, need to wait for an interrupt. Since D1 was high,
|
||||
@ -627,3 +578,34 @@ static void sdmmc_isr(void* arg) {
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t sdmmc_host_pullup_en(int slot, int width)
|
||||
{
|
||||
if (width > sdmmc_slot_info[slot].width) {
|
||||
//in esp32 we only support 8 bit in slot 0, note this is occupied by the flash by default
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
//according to the spec, the host control the clk, we don't to pull it up here
|
||||
gpio_pullup_en(sdmmc_slot_info[slot].cmd_gpio);
|
||||
gpio_pulldown_dis(sdmmc_slot_info[slot].cmd_gpio);
|
||||
gpio_pullup_en(sdmmc_slot_info[slot].d0_gpio);
|
||||
gpio_pulldown_dis(sdmmc_slot_info[slot].d0_gpio);
|
||||
if (width >= 4) {
|
||||
gpio_pullup_en(sdmmc_slot_info[slot].d1_gpio);
|
||||
gpio_pulldown_dis(sdmmc_slot_info[slot].d1_gpio);
|
||||
gpio_pullup_en(sdmmc_slot_info[slot].d2_gpio);
|
||||
gpio_pulldown_dis(sdmmc_slot_info[slot].d2_gpio);
|
||||
gpio_pullup_en(sdmmc_slot_info[slot].d3_gpio);
|
||||
gpio_pulldown_dis(sdmmc_slot_info[slot].d3_gpio);
|
||||
}
|
||||
if (width == 8) {
|
||||
gpio_pullup_en(sdmmc_slot_info[slot].d4_gpio);
|
||||
gpio_pulldown_dis(sdmmc_slot_info[slot].d4_gpio);
|
||||
gpio_pullup_en(sdmmc_slot_info[slot].d5_gpio);
|
||||
gpio_pulldown_dis(sdmmc_slot_info[slot].d5_gpio);
|
||||
gpio_pullup_en(sdmmc_slot_info[slot].d6_gpio);
|
||||
gpio_pulldown_dis(sdmmc_slot_info[slot].d6_gpio);
|
||||
gpio_pullup_en(sdmmc_slot_info[slot].d7_gpio);
|
||||
gpio_pulldown_dis(sdmmc_slot_info[slot].d7_gpio);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
@ -19,7 +19,7 @@
|
||||
#include "esp_err.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "soc/sdmmc_struct.h"
|
||||
#include "soc/sdmmc_periph.h"
|
||||
|
||||
typedef struct {
|
||||
uint32_t sdmmc_status; ///< masked SDMMC interrupt status
|
||||
|
@ -19,8 +19,7 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "soc/sdmmc_reg.h"
|
||||
#include "soc/sdmmc_struct.h"
|
||||
#include "soc/sdmmc_periph.h"
|
||||
#include "soc/soc_memory_layout.h"
|
||||
#include "driver/sdmmc_types.h"
|
||||
#include "driver/sdmmc_defs.h"
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include "esp_log.h"
|
||||
#include "sys/lock.h"
|
||||
#include "soc/sdmmc_reg.h"
|
||||
#include "soc/sdmmc_struct.h"
|
||||
#include "soc/sdmmc_periph.h"
|
||||
#include "driver/sdmmc_types.h"
|
||||
#include "driver/sdmmc_defs.h"
|
||||
#include "driver/sdmmc_host.h"
|
||||
|
34
components/soc/esp32/include/soc/sdio_slave_pins.h
Normal file
34
components/soc/esp32/include/soc/sdio_slave_pins.h
Normal file
@ -0,0 +1,34 @@
|
||||
// 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_SDIO_SLAVE_PINS_H_
|
||||
#define _SOC_SDIO_SLAVE_PINS_H_
|
||||
|
||||
#define SDIO_SLAVE_SLOT0_IOMUX_PIN_NUM_CLK 6
|
||||
#define SDIO_SLAVE_SLOT0_IOMUX_PIN_NUM_CMD 11
|
||||
#define SDIO_SLAVE_SLOT0_IOMUX_PIN_NUM_D0 7
|
||||
#define SDIO_SLAVE_SLOT0_IOMUX_PIN_NUM_D1 8
|
||||
#define SDIO_SLAVE_SLOT0_IOMUX_PIN_NUM_D2 9
|
||||
#define SDIO_SLAVE_SLOT0_IOMUX_PIN_NUM_D3 10
|
||||
#define SDIO_SLAVE_SLOT0_FUNC 0
|
||||
|
||||
#define SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_CLK 14
|
||||
#define SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_CMD 15
|
||||
#define SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_D0 2
|
||||
#define SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_D1 4
|
||||
#define SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_D2 12
|
||||
#define SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_D3 13
|
||||
#define SDIO_SLAVE_SLOT1_FUNC 4
|
||||
|
||||
#endif /* _SOC_SDIO_SLAVE_PINS_H_ */
|
38
components/soc/esp32/include/soc/sdmmc_pins.h
Normal file
38
components/soc/esp32/include/soc/sdmmc_pins.h
Normal file
@ -0,0 +1,38 @@
|
||||
// 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 6
|
||||
#define SDMMC_SLOT0_IOMUX_PIN_NUM_CMD 11
|
||||
#define SDMMC_SLOT0_IOMUX_PIN_NUM_D0 7
|
||||
#define SDMMC_SLOT0_IOMUX_PIN_NUM_D1 8
|
||||
#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 14
|
||||
#define SDMMC_SLOT1_IOMUX_PIN_NUM_CMD 15
|
||||
#define SDMMC_SLOT1_IOMUX_PIN_NUM_D0 2
|
||||
#define SDMMC_SLOT1_IOMUX_PIN_NUM_D1 4
|
||||
#define SDMMC_SLOT1_IOMUX_PIN_NUM_D2 12
|
||||
#define SDMMC_SLOT1_IOMUX_PIN_NUM_D3 13
|
||||
#define SDMMC_SLOT1_FUNC 4
|
||||
|
||||
#endif /* _SOC_SDMMC_PINS_H_ */
|
43
components/soc/esp32/sdio_slave_periph.c
Normal file
43
components/soc/esp32/sdio_slave_periph.c
Normal file
@ -0,0 +1,43 @@
|
||||
// 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.
|
||||
|
||||
#include <stdint.h>
|
||||
#include "soc/sdio_slave_periph.h"
|
||||
#include "soc/io_mux_reg.h"
|
||||
#include "soc/sdio_slave_pins.h"
|
||||
|
||||
// I/O slot of sdio slave:
|
||||
// 0: GPIO 6, 11, 7, 8, 9, 10,
|
||||
// 1: GPIO 14, 15, 2, 4, 12, 13 for CLK, CMD, D0, D1, D2, D3 respectively.
|
||||
// only one peripheral for SDIO and only one slot can work at the same time.
|
||||
// currently slot 0 is occupied by SPI for flash
|
||||
const sdio_slave_slot_info_t sdio_slave_slot_info[2] = {
|
||||
{
|
||||
.clk_gpio = SDIO_SLAVE_SLOT0_IOMUX_PIN_NUM_CLK,
|
||||
.cmd_gpio = SDIO_SLAVE_SLOT0_IOMUX_PIN_NUM_CMD,
|
||||
.d0_gpio = SDIO_SLAVE_SLOT0_IOMUX_PIN_NUM_D0,
|
||||
.d1_gpio = SDIO_SLAVE_SLOT0_IOMUX_PIN_NUM_D1,
|
||||
.d2_gpio = SDIO_SLAVE_SLOT0_IOMUX_PIN_NUM_D2,
|
||||
.d3_gpio = SDIO_SLAVE_SLOT0_IOMUX_PIN_NUM_D3,
|
||||
.func = SDIO_SLAVE_SLOT0_FUNC,
|
||||
}, {
|
||||
.clk_gpio = SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_CLK,
|
||||
.cmd_gpio = SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_CMD,
|
||||
.d0_gpio = SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_D0,
|
||||
.d1_gpio = SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_D1,
|
||||
.d2_gpio = SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_D2,
|
||||
.d3_gpio = SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_D3,
|
||||
.func = SDIO_SLAVE_SLOT1_FUNC,
|
||||
},
|
||||
};
|
50
components/soc/esp32/sdmmc_periph.c
Normal file
50
components/soc/esp32/sdmmc_periph.c
Normal file
@ -0,0 +1,50 @@
|
||||
// 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.
|
||||
|
||||
#include "soc/sdmmc_periph.h"
|
||||
|
||||
const sdmmc_slot_info_t sdmmc_slot_info[2] = {
|
||||
{
|
||||
.clk_gpio = SDMMC_SLOT0_IOMUX_PIN_NUM_CLK,
|
||||
.cmd_gpio = SDMMC_SLOT0_IOMUX_PIN_NUM_CMD,
|
||||
.d0_gpio = SDMMC_SLOT0_IOMUX_PIN_NUM_D0,
|
||||
.d1_gpio = SDMMC_SLOT0_IOMUX_PIN_NUM_D1,
|
||||
.d2_gpio = SDMMC_SLOT0_IOMUX_PIN_NUM_D2,
|
||||
.d3_gpio = SDMMC_SLOT0_IOMUX_PIN_NUM_D3,
|
||||
.d4_gpio = SDMMC_SLOT0_IOMUX_PIN_NUM_D4,
|
||||
.d5_gpio = SDMMC_SLOT0_IOMUX_PIN_NUM_D5,
|
||||
.d6_gpio = SDMMC_SLOT0_IOMUX_PIN_NUM_D6,
|
||||
.d7_gpio = SDMMC_SLOT0_IOMUX_PIN_NUM_D7,
|
||||
.card_detect = HOST_CARD_DETECT_N_1_IDX,
|
||||
.write_protect = HOST_CARD_WRITE_PRT_1_IDX,
|
||||
.card_int = HOST_CARD_INT_N_1_IDX,
|
||||
.width = 8
|
||||
},
|
||||
{
|
||||
.clk_gpio = SDMMC_SLOT1_IOMUX_PIN_NUM_CLK,
|
||||
.cmd_gpio = SDMMC_SLOT1_IOMUX_PIN_NUM_CMD,
|
||||
.d0_gpio = SDMMC_SLOT1_IOMUX_PIN_NUM_D0,
|
||||
.d1_gpio = SDMMC_SLOT1_IOMUX_PIN_NUM_D1,
|
||||
.d2_gpio = SDMMC_SLOT1_IOMUX_PIN_NUM_D2,
|
||||
.d3_gpio = SDMMC_SLOT1_IOMUX_PIN_NUM_D3,
|
||||
.d4_gpio = -1, //slot1 has no D4-7
|
||||
.d5_gpio = -1,
|
||||
.d6_gpio = -1,
|
||||
.d7_gpio = -1,
|
||||
.card_detect = HOST_CARD_DETECT_N_2_IDX,
|
||||
.write_protect = HOST_CARD_WRITE_PRT_2_IDX,
|
||||
.card_int = HOST_CARD_INT_N_2_IDX,
|
||||
.width = 4
|
||||
}
|
||||
};
|
49
components/soc/include/soc/sdio_slave_periph.h
Normal file
49
components/soc/include/soc/sdio_slave_periph.h
Normal file
@ -0,0 +1,49 @@
|
||||
// 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_SDIO_SLAVE_PERIPH_H_
|
||||
#define _SOC_SDIO_SLAVE_PERIPH_H_
|
||||
|
||||
#include <stdint.h>
|
||||
//include soc related (generated) definitions
|
||||
#include "soc/sdio_slave_pins.h"
|
||||
#include "soc/slc_reg.h"
|
||||
#include "soc/slc_struct.h"
|
||||
#include "soc/host_reg.h"
|
||||
#include "soc/host_struct.h"
|
||||
#include "soc/hinf_reg.h"
|
||||
#include "soc/hinf_struct.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** pin and signal information of each slot */
|
||||
typedef struct {
|
||||
uint32_t clk_gpio;
|
||||
uint32_t cmd_gpio;
|
||||
uint32_t d0_gpio;
|
||||
uint32_t d1_gpio;
|
||||
uint32_t d2_gpio;
|
||||
uint32_t d3_gpio;
|
||||
int func;
|
||||
} sdio_slave_slot_info_t;
|
||||
|
||||
extern const sdio_slave_slot_info_t sdio_slave_slot_info[];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _SOC_SDIO_SLAVE_PERIPH_H_ */
|
53
components/soc/include/soc/sdmmc_periph.h
Normal file
53
components/soc/include/soc/sdmmc_periph.h
Normal file
@ -0,0 +1,53 @@
|
||||
// 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_PERIPH_H_
|
||||
#define _SOC_SDMMC_PERIPH_H_
|
||||
|
||||
#include <stdint.h>
|
||||
//include soc related (generated) definitions
|
||||
#include "soc/sdmmc_pins.h"
|
||||
#include "soc/sdmmc_reg.h"
|
||||
#include "soc/sdmmc_struct.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint8_t clk_gpio;
|
||||
uint8_t cmd_gpio;
|
||||
uint8_t d0_gpio;
|
||||
uint8_t d1_gpio;
|
||||
uint8_t d2_gpio;
|
||||
uint8_t d3_gpio;
|
||||
uint8_t d4_gpio;
|
||||
uint8_t d5_gpio;
|
||||
uint8_t d6_gpio;
|
||||
uint8_t d7_gpio;
|
||||
uint8_t card_detect;
|
||||
uint8_t write_protect;
|
||||
uint8_t card_int;
|
||||
uint8_t width;
|
||||
} sdmmc_slot_info_t;
|
||||
|
||||
/** pin and signal information of each slot */
|
||||
extern const sdmmc_slot_info_t sdmmc_slot_info[];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _SOC_SDMMC_PERIPH_H_ */
|
153
docs/en/api-reference/peripherals/sd_pullup_requirements.rst
Normal file
153
docs/en/api-reference/peripherals/sd_pullup_requirements.rst
Normal file
@ -0,0 +1,153 @@
|
||||
SD Pullup Requirements
|
||||
======================
|
||||
|
||||
CMD and DATA lines D0-D3 of the slave should be pulled up by 50KOhm resistor
|
||||
even in 1-bit mode or SPI mode. The pullups of the slave cards should be
|
||||
connected even if they're not connected to the host.
|
||||
|
||||
The MTDI strapping pin is incompatible with DAT2 line pull-up by default
|
||||
when the code flash is 3.3V. See :ref:`mtdi_strapping_pin` below.
|
||||
|
||||
Pullup inside Official Modules
|
||||
------------------------------
|
||||
|
||||
For Espressif official modules, different weak pullups / pulldowns are
|
||||
connected to CMD, and DATA pins as below. To use these modules,
|
||||
these pins are required to be pulled up by 50KOhm resistors, since internal
|
||||
weak pullups are insufficient.
|
||||
|
||||
+-----------------------+-----+--------------------------+------+----------------------+------+
|
||||
| GPIO | 15 | 2 | 4 | 12 | 13 |
|
||||
+=======================+=====+==========================+======+======================+======+
|
||||
| Name | CMD | DAT0 | DAT1 | DAT2 | DAT3 |
|
||||
+-----------------------+-----+--------------------------+------+----------------------+------+
|
||||
| At startup | WPU | WPD | WPD | PU for 1.8v flash; | WPU |
|
||||
| | | | | WPD for 3.3v flash | |
|
||||
+-----------------------+-----+--------------------------+------+----------------------+------+
|
||||
| Strapping requirement | | Low to download to flash | | High for 1.8v flash; | |
|
||||
| | | | | Low for 3.3v flash | |
|
||||
+-----------------------+-----+--------------------------+------+----------------------+------+
|
||||
|
||||
- WPU: Weak pullup
|
||||
- WPD: Weak pulldown
|
||||
- PU: Pullup inside the module
|
||||
|
||||
For Wrover modules, they use 1.8v flash, and have pullup on GPIO12 inside.
|
||||
For Wroom-32 Series, PICO-D4 modules, they use 3.3v flash, and is weakly
|
||||
pulled down internally. See :ref:`mtdi_strapping_pin` below.
|
||||
|
||||
Pullup on Official Devkit (WroverKit)
|
||||
--------------------------------------
|
||||
|
||||
For official Wrover Kit (till version 3), some of the pullups are provided on
|
||||
the board as the table below. For other devkits that don't have pullups,
|
||||
please connect them yourselves.
|
||||
|
||||
+-----------------------+-----+------+------+------+---------+
|
||||
| GPIO | 15 | 2 | 4 | 12 | 13 |
|
||||
+=======================+=====+======+======+======+=========+
|
||||
| Name | CMD | DAT0 | DAT1 | DAT2 | DAT3 |
|
||||
+-----------------------+-----+------+------+------+---------+
|
||||
| Pullup on the Kit | PU | PU | PU | | PU & PD |
|
||||
+-----------------------+-----+------+------+------+---------+
|
||||
|
||||
- PU: Pullup
|
||||
- PD: Pulldown
|
||||
|
||||
The DAT3 pullup conflicts with JTAG pulldown in WroverKit v3 and earlier, please
|
||||
either:
|
||||
|
||||
1. pull it up by resistor less than 5KOhm (2kOhm suggested) in 4-bit mode.
|
||||
2. pull it up or drive it high by host or VDD3.3V in 1-bit mode.
|
||||
|
||||
.. _mtdi_strapping_pin:
|
||||
|
||||
MTDI strapping pin
|
||||
------------------
|
||||
|
||||
MTDI (GPIO12) is used as a bootstrapping pin to select output voltage of an
|
||||
internal regulator which powers the flash chip (VDD_SDIO). This pin has an
|
||||
internal pulldown so if left unconnected it will read low at reset (selecting
|
||||
default 3.3V operation). When adding a pullup to this pin for SD card
|
||||
operation, consider the following:
|
||||
|
||||
- For boards which don't use the internal regulator (VDD_SDIO) to power the
|
||||
flash, GPIO12 can be pulled high.
|
||||
- For boards which use 1.8V flash chip, GPIO12 needs to be pulled high at
|
||||
reset. This is fully compatible with SD card operation.
|
||||
- On boards which use the internal regulator and a 3.3V flash chip, GPIO12
|
||||
must be low at reset. This is incompatible with SD card operation. Please
|
||||
check the table below to see whether your modules/kits use 3.3v flash.
|
||||
|
||||
+-----------------+---------------+--------------------------------------+
|
||||
| Module | Flash voltage | DAT2 connections |
|
||||
+=================+===============+======================================+
|
||||
| PICO-D4 | 3.3V | Internal PD, change EFUSE and pullup |
|
||||
+-----------------+ + or disable DAT2 line* +
|
||||
| Wroom-32 Series | | |
|
||||
+-----------------+---------------+--------------------------------------+
|
||||
| Wrover | 1.8V | Internal PU, pullup suggested |
|
||||
+-----------------+---------------+--------------------------------------+
|
||||
|
||||
Official devkits of different types and version mount different types of
|
||||
modules, please refer to the table below to see whether your devkit can
|
||||
support SDIO slave without steps above.
|
||||
|
||||
+--------------------------+-----------------+---------------+
|
||||
| Devkit | Module | Flash voltage |
|
||||
+==========================+=================+===============+
|
||||
| PICO Kit | PICO-D4 | 3.3V |
|
||||
+--------------------------+-----------------+ (see steps +
|
||||
| DevKitC | Wroom-32 Series | below) |
|
||||
+--------------------------+ + +
|
||||
| WroverKit v2 and earlier | | |
|
||||
+--------------------------+-----------------+---------------+
|
||||
| WroverKit v3 | Wrover | 1.8V |
|
||||
+--------------------------+-----------------+---------------+
|
||||
|
||||
If your board requires internal regulator with 3.3v output, to make it
|
||||
compatible with SD pullup, you can either:
|
||||
|
||||
- **In the case using ESP32 host only**, external pullup can be omitted and an
|
||||
internal pullup can be enabled using a ``gpio_pullup_en(GPIO_NUM_12);`` call.
|
||||
Most SD cards work fine when an internal pullup on GPIO12 line is enabled.
|
||||
Note that if ESP32 experiences a power-on reset while the SD card is
|
||||
sending data, high level on GPIO12 can be latched into the bootstrapping
|
||||
register, and ESP32 will enter a boot loop until external reset with
|
||||
correct GPIO12 level is applied.
|
||||
- **In the case using ESP32 slave in 1-bit mode**, speicfy
|
||||
``SDIO_SLAVE_FLAG_DAT2_DISABLED`` in the slave to avoid slave detecting on
|
||||
DAT2 line. Note the host will not know 4-bit mode is not supported any more
|
||||
by the standard CCCR register. You have to tell the host use 1-bit only.
|
||||
- **For ESP32 host or slave**, another option is to burn the flash voltage
|
||||
selection efuses. This will permanently select 3.3V output voltage for the
|
||||
internal regulator, and GPIO12 will not be used as a bootstrapping pin.
|
||||
Then it is safe to connect a pullup resistor to GPIO12. This option is
|
||||
suggested for production use. NOTE this cannot be reverted once the EFUSE
|
||||
is burnt.
|
||||
|
||||
The following command can be used to program flash voltage selection efuses **to 3.3V**:
|
||||
|
||||
components/esptool_py/esptool/espefuse.py set_flash_voltage 3.3V
|
||||
|
||||
This command will burn the `XPD_SDIO_TIEH`, `XPD_SDIO_FORCE`, and
|
||||
`XPD_SDIO_REG` efuses. With all three burned to value 1, the internal
|
||||
VDD_SDIO flash voltage regulator is permanently enabled at 3.3V. See
|
||||
the technical reference manual for more details.
|
||||
|
||||
`espefuse.py` has a `--do-not-confirm` option if running from an automated flashing script.
|
||||
|
||||
GPIO2 Strapping pin
|
||||
-------------------
|
||||
|
||||
GPIO2 pin is used as a bootstrapping pin, and should be low to enter UART
|
||||
download mode. You may find it unable to enter the UART download mode if you
|
||||
correctly connect the pullup of SD on GPIO2. For WroverKit v3, there are
|
||||
dedicated circuits to pulldown the GPIO2 when downloading. For other boards,
|
||||
one way to do this is to connect GPIO0 and GPIO2 using a jumper, and then the
|
||||
auto-reset circuit on most development boards will pull GPIO2 low along with
|
||||
GPIO0, when entering download mode.
|
||||
|
||||
- Some boards have pulldown and/or LED on GPIO2. LED is usually ok, but
|
||||
pulldown will interfere with D0 signals and must be removed. Check the
|
||||
schematic of your development board for anything connected to GPIO2.
|
@ -4,9 +4,6 @@ SDIO Card Slave Driver
|
||||
Overview
|
||||
--------
|
||||
|
||||
.. note:: At the moment, this code has been proven to work on the Wrover-Kit V3. Earlier versions of the Wrover-Kit
|
||||
and other development kits are electrically incompatible with this code. Functionality on other devboards is untested.
|
||||
|
||||
The ESP32 SDIO Card peripherals (Host, Slave) shares two sets of pins as below table.
|
||||
The first set is usually occupied by SPI0 bus which is responsible for the SPI flash holding the code to run.
|
||||
This means SDIO slave driver can only runs on the second set of pins while SDIO host is not using it.
|
||||
@ -29,15 +26,33 @@ This means SDIO slave driver can only runs on the second set of pins while SDIO
|
||||
| DAT3 | 10 | 13 |
|
||||
+----------+-------+-------+
|
||||
|
||||
The SDIO slave can run under 3 modes: SPI, 1-bit SD and 4-bit SD modes, which is detected automatically by the
|
||||
hardware. According to the SDIO specification, the host initialize the slave into SD mode by first sending CMD0 with
|
||||
DAT3 pin high, while initialize the slave into SPI mode by sending CMD0 with CS pin (the same pin as DAT3) low. After the
|
||||
initialization, the host can enable the 4-bit SD mode by writing CCCR register 0x07 by CMD52. All the bus detection
|
||||
process are handled by the slave peripheral.
|
||||
The SDIO slave can run under 3 modes: SPI, 1-bit SD and 4-bit SD modes, which
|
||||
is detected automatically by the hardware. According to the SDIO
|
||||
specification, CMD and DAT0-3 lines should be pulled up no matter in 1-bit,
|
||||
4-bit or SPI mode. Then the host initialize the slave into SD mode by first
|
||||
sending CMD0 with DAT3 pin high, while initialize the slave into SPI mode by
|
||||
sending CMD0 with CS pin (the same pin as DAT3) low.
|
||||
|
||||
The host has to communicate with the slave by an ESP-slave-specific protocol. The slave driver offers 3 services over
|
||||
Function 1 access by CMD52 and CMD53: (1) a sending FIFO and a receiving FIFO, (2) 52 8-bit R/W registers shared by
|
||||
host and slave, (3) 16 interrupt sources (8 from host to slave, and 8 from slave to host).
|
||||
.. note:: CMD and DATA lines D0-D3 of the card should be pulled up by 50KOhm resistor
|
||||
even in 1-bit mode or SPI mode. Most official devkits don't meet the pullup
|
||||
requirements by default, and there are conflicts on strapping pins as well.
|
||||
Please refer to :doc:`sd_pullup_requirements` to see how to setup your
|
||||
system correctly.
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
|
||||
sd_pullup_requirements
|
||||
|
||||
After the initialization, the host can enable the 4-bit SD mode by writing
|
||||
CCCR register 0x07 by CMD52. All the bus detection process are handled by the
|
||||
slave peripheral.
|
||||
|
||||
The host has to communicate with the slave by an ESP-slave-specific protocol.
|
||||
The slave driver offers 3 services over Function 1 access by CMD52 and CMD53:
|
||||
(1) a sending FIFO and a receiving FIFO, (2) 52 8-bit R/W registers shared by
|
||||
host and slave, (3) 16 interrupt sources (8 from host to slave, and 8 from
|
||||
slave to host).
|
||||
|
||||
Terminology
|
||||
^^^^^^^^^^^
|
||||
@ -215,6 +230,7 @@ There are several ways to use the ``arg`` in the queue parameter:
|
||||
|
||||
More about this, see :example:`peripherals/sdio`.
|
||||
|
||||
|
||||
Application Example
|
||||
-------------------
|
||||
|
||||
|
@ -60,6 +60,8 @@ See :doc:`SD/SDIO/MMC Driver <../storage/sdmmc>` for the higher level driver whi
|
||||
|
||||
See :doc:`SD SPI Host Driver <sdspi_host>` for a similar driver which uses SPI controller and is limited to SPI mode of SD protocol.
|
||||
|
||||
See :doc:`sd_pullup_requirements` for pullup support and compatiblities about modules and devkits.
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
|
||||
|
@ -0,0 +1 @@
|
||||
.. include:: ../../../en/api-reference/peripherals/sd_pullup_requirements.rst
|
Loading…
x
Reference in New Issue
Block a user