Merge branch 'fix/sdio_speed_4bit_v3.1' into 'release/v3.1'
backport v3.1: fix(sdio): update sdio to better run in 4bit HS mode See merge request idf/esp-idf!2759
This commit is contained in:
commit
cb05e152b9
3 changed files with 102 additions and 90 deletions
|
@ -47,10 +47,12 @@ typedef enum {
|
||||||
|
|
||||||
/// Timing of SDIO slave
|
/// Timing of SDIO slave
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SDIO_SLAVE_TIMING_NSEND_PSAMPLE = 0,///< Send at negedge, and sample at posedge. Default value for SD protocol.
|
SDIO_SLAVE_TIMING_PSEND_PSAMPLE = 0,/**< Send at posedge, and sample at posedge. Default value for HS mode.
|
||||||
SDIO_SLAVE_TIMING_NSEND_NSAMPLE, ///< Send at negedge, and sample at negedge
|
* Normally there's no problem using this to work in DS mode.
|
||||||
SDIO_SLAVE_TIMING_PSEND_PSAMPLE, ///< Send at posedge, and sample at posedge
|
*/
|
||||||
|
SDIO_SLAVE_TIMING_NSEND_PSAMPLE ,///< Send at negedge, and sample at posedge. Default value for DS mode and below.
|
||||||
SDIO_SLAVE_TIMING_PSEND_NSAMPLE, ///< Send at posedge, and sample at negedge
|
SDIO_SLAVE_TIMING_PSEND_NSAMPLE, ///< Send at posedge, and sample at negedge
|
||||||
|
SDIO_SLAVE_TIMING_NSEND_NSAMPLE, ///< Send at negedge, and sample at negedge
|
||||||
} sdio_slave_timing_t;
|
} sdio_slave_timing_t;
|
||||||
|
|
||||||
/// Configuration of SDIO slave mode
|
/// Configuration of SDIO slave mode
|
||||||
|
@ -197,12 +199,12 @@ uint8_t* sdio_slave_recv_get_buf( sdio_slave_buf_handle_t handle, size_t *len_o)
|
||||||
esp_err_t sdio_slave_send_queue(uint8_t* addr, size_t len, void* arg, TickType_t wait);
|
esp_err_t sdio_slave_send_queue(uint8_t* addr, size_t len, void* arg, TickType_t wait);
|
||||||
|
|
||||||
/** Return the ownership of a finished transaction.
|
/** Return the ownership of a finished transaction.
|
||||||
* @param arg_o Argument of the finished transaction.
|
* @param out_arg Argument of the finished transaction. Set to NULL if unused.
|
||||||
* @param wait Time to wait if there's no finished sending transaction.
|
* @param wait Time to wait if there's no finished sending transaction.
|
||||||
*
|
*
|
||||||
* @return ESP_ERR_TIMEOUT if no transaction finished, or ESP_OK if succeed.
|
* @return ESP_ERR_TIMEOUT if no transaction finished, or ESP_OK if succeed.
|
||||||
*/
|
*/
|
||||||
esp_err_t sdio_slave_send_get_finished(void** arg_o, TickType_t wait);
|
esp_err_t sdio_slave_send_get_finished(void** out_arg, TickType_t wait);
|
||||||
|
|
||||||
/** Start a new sending transfer, and wait for it (blocked) to be finished.
|
/** Start a new sending transfer, and wait for it (blocked) to be finished.
|
||||||
*
|
*
|
||||||
|
|
|
@ -120,12 +120,12 @@ typedef enum {
|
||||||
} send_state_t;
|
} send_state_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t clk;
|
uint32_t clk_gpio;
|
||||||
uint32_t cmd;
|
uint32_t cmd_gpio;
|
||||||
uint32_t d0;
|
uint32_t d0_gpio;
|
||||||
uint32_t d1;
|
uint32_t d1_gpio;
|
||||||
uint32_t d2;
|
uint32_t d2_gpio;
|
||||||
uint32_t d3;
|
uint32_t d3_gpio;
|
||||||
int func;
|
int func;
|
||||||
} sdio_slave_slot_info_t ;
|
} sdio_slave_slot_info_t ;
|
||||||
|
|
||||||
|
@ -136,20 +136,20 @@ typedef struct {
|
||||||
// currently slot 0 is occupied by SPI for flash
|
// currently slot 0 is occupied by SPI for flash
|
||||||
static const sdio_slave_slot_info_t s_slot_info[2] = {
|
static const sdio_slave_slot_info_t s_slot_info[2] = {
|
||||||
{
|
{
|
||||||
.clk = PERIPHS_IO_MUX_SD_CLK_U,
|
.clk_gpio = 6,
|
||||||
.cmd = PERIPHS_IO_MUX_SD_CMD_U,
|
.cmd_gpio = 11,
|
||||||
.d0 = PERIPHS_IO_MUX_SD_DATA0_U,
|
.d0_gpio = 7,
|
||||||
.d1 = PERIPHS_IO_MUX_SD_DATA1_U,
|
.d1_gpio = 8,
|
||||||
.d2 = PERIPHS_IO_MUX_SD_DATA2_U,
|
.d2_gpio = 9,
|
||||||
.d3 = PERIPHS_IO_MUX_SD_DATA3_U,
|
.d3_gpio = 10,
|
||||||
.func = 0,
|
.func = 0,
|
||||||
}, {
|
}, {
|
||||||
.clk = PERIPHS_IO_MUX_MTMS_U,
|
.clk_gpio = 14,
|
||||||
.cmd = PERIPHS_IO_MUX_MTDO_U,
|
.cmd_gpio = 15,
|
||||||
.d0 = PERIPHS_IO_MUX_GPIO2_U,
|
.d0_gpio = 2,
|
||||||
.d1 = PERIPHS_IO_MUX_GPIO4_U,
|
.d1_gpio = 4,
|
||||||
.d2 = PERIPHS_IO_MUX_MTDI_U,
|
.d2_gpio = 12,
|
||||||
.d3 = PERIPHS_IO_MUX_MTCK_U,
|
.d3_gpio = 13,
|
||||||
.func = 4,
|
.func = 4,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -499,13 +499,18 @@ no_mem:
|
||||||
return ESP_ERR_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 sdmmc_func = func;
|
||||||
const int drive_strength = 3;
|
const int drive_strength = 3;
|
||||||
PIN_INPUT_ENABLE(io_mux_reg);
|
assert(pin!=-1);
|
||||||
PIN_FUNC_SELECT(io_mux_reg, sdmmc_func);
|
uint32_t reg = GPIO_PIN_MUX_REG[pin];
|
||||||
PIN_SET_DRV(io_mux_reg, drive_strength);
|
assert(reg!=0);
|
||||||
|
|
||||||
|
PIN_INPUT_ENABLE(reg);
|
||||||
|
PIN_FUNC_SELECT(reg, sdmmc_func);
|
||||||
|
PIN_SET_DRV(reg, drive_strength);
|
||||||
|
gpio_pulldown_dis(pin);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline esp_err_t sdio_slave_hw_init(sdio_slave_config_t *config)
|
static inline esp_err_t sdio_slave_hw_init(sdio_slave_config_t *config)
|
||||||
|
@ -515,12 +520,13 @@ static inline esp_err_t sdio_slave_hw_init(sdio_slave_config_t *config)
|
||||||
|
|
||||||
//initialize pin
|
//initialize pin
|
||||||
const sdio_slave_slot_info_t *slot = &s_slot_info[1];
|
const sdio_slave_slot_info_t *slot = &s_slot_info[1];
|
||||||
configure_pin(slot->clk, slot->func);
|
configure_pin(slot->clk_gpio, slot->func, false); //clk doesn't need a pullup
|
||||||
configure_pin(slot->cmd, slot->func);
|
configure_pin(slot->cmd_gpio, slot->func, false);
|
||||||
configure_pin(slot->d0, slot->func);
|
configure_pin(slot->d0_gpio, slot->func, false);
|
||||||
configure_pin(slot->d1, slot->func);
|
configure_pin(slot->d1_gpio, slot->func, false);
|
||||||
configure_pin(slot->d2, slot->func);
|
configure_pin(slot->d2_gpio, slot->func, false);
|
||||||
configure_pin(slot->d3, slot->func);
|
configure_pin(slot->d3_gpio, slot->func, false);
|
||||||
|
|
||||||
//enable module and config
|
//enable module and config
|
||||||
periph_module_reset(PERIPH_SDIO_SLAVE_MODULE);
|
periph_module_reset(PERIPH_SDIO_SLAVE_MODULE);
|
||||||
periph_module_enable(PERIPH_SDIO_SLAVE_MODULE);
|
periph_module_enable(PERIPH_SDIO_SLAVE_MODULE);
|
||||||
|
@ -539,28 +545,28 @@ static inline esp_err_t sdio_slave_hw_init(sdio_slave_config_t *config)
|
||||||
|
|
||||||
switch( config->timing ) {
|
switch( config->timing ) {
|
||||||
case SDIO_SLAVE_TIMING_PSEND_PSAMPLE:
|
case SDIO_SLAVE_TIMING_PSEND_PSAMPLE:
|
||||||
HOST.conf.frc_sdio20 = 0xf;
|
HOST.conf.frc_sdio20 = 0x1f;
|
||||||
HOST.conf.frc_sdio11 = 0;
|
HOST.conf.frc_sdio11 = 0;
|
||||||
HOST.conf.frc_pos_samp = 0xf;
|
HOST.conf.frc_pos_samp = 0x1f;
|
||||||
HOST.conf.frc_neg_samp = 0;
|
HOST.conf.frc_neg_samp = 0;
|
||||||
break;
|
break;
|
||||||
case SDIO_SLAVE_TIMING_PSEND_NSAMPLE:
|
case SDIO_SLAVE_TIMING_PSEND_NSAMPLE:
|
||||||
HOST.conf.frc_sdio20 = 0xf;
|
HOST.conf.frc_sdio20 = 0x1f;
|
||||||
HOST.conf.frc_sdio11 = 0;
|
HOST.conf.frc_sdio11 = 0;
|
||||||
HOST.conf.frc_pos_samp = 0;
|
HOST.conf.frc_pos_samp = 0;
|
||||||
HOST.conf.frc_neg_samp = 0xf;
|
HOST.conf.frc_neg_samp = 0x1f;
|
||||||
break;
|
break;
|
||||||
case SDIO_SLAVE_TIMING_NSEND_PSAMPLE:
|
case SDIO_SLAVE_TIMING_NSEND_PSAMPLE:
|
||||||
HOST.conf.frc_sdio20 = 0;
|
HOST.conf.frc_sdio20 = 0;
|
||||||
HOST.conf.frc_sdio11 = 0xf;
|
HOST.conf.frc_sdio11 = 0x1f;
|
||||||
HOST.conf.frc_pos_samp = 0xf;
|
HOST.conf.frc_pos_samp = 0x1f;
|
||||||
HOST.conf.frc_neg_samp = 0;
|
HOST.conf.frc_neg_samp = 0;
|
||||||
break;
|
break;
|
||||||
case SDIO_SLAVE_TIMING_NSEND_NSAMPLE:
|
case SDIO_SLAVE_TIMING_NSEND_NSAMPLE:
|
||||||
HOST.conf.frc_sdio20 = 0;
|
HOST.conf.frc_sdio20 = 0;
|
||||||
HOST.conf.frc_sdio11 = 0xf;
|
HOST.conf.frc_sdio11 = 0x1f;
|
||||||
HOST.conf.frc_pos_samp = 0;
|
HOST.conf.frc_pos_samp = 0;
|
||||||
HOST.conf.frc_neg_samp = 0xf;
|
HOST.conf.frc_neg_samp = 0x1f;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -952,9 +958,11 @@ esp_err_t sdio_slave_send_queue(uint8_t* addr, size_t len, void* arg, TickType_t
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t sdio_slave_send_get_finished(void** arg, TickType_t wait)
|
esp_err_t sdio_slave_send_get_finished(void** out_arg, TickType_t wait)
|
||||||
{
|
{
|
||||||
portBASE_TYPE err = xQueueReceive( context.ret_queue, arg, wait );
|
void* arg = NULL;
|
||||||
|
portBASE_TYPE err = xQueueReceive(context.ret_queue, &arg, wait);
|
||||||
|
if (out_arg) *out_arg = arg;
|
||||||
if ( err != pdTRUE ) return ESP_ERR_TIMEOUT;
|
if ( err != pdTRUE ) return ESP_ERR_TIMEOUT;
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,18 +31,16 @@
|
||||||
#define SDMMC_EVENT_QUEUE_LENGTH 32
|
#define SDMMC_EVENT_QUEUE_LENGTH 32
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t clk;
|
uint8_t clk_gpio;
|
||||||
uint32_t cmd;
|
uint8_t cmd_gpio;
|
||||||
uint32_t d0;
|
uint8_t d0_gpio;
|
||||||
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 d1_gpio;
|
||||||
|
uint8_t d2_gpio;
|
||||||
uint8_t d3_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 card_detect;
|
||||||
uint8_t write_protect;
|
uint8_t write_protect;
|
||||||
uint8_t card_int;
|
uint8_t card_int;
|
||||||
|
@ -55,32 +53,32 @@ static void sdmmc_host_dma_init();
|
||||||
|
|
||||||
static const sdmmc_slot_info_t s_slot_info[2] = {
|
static const sdmmc_slot_info_t s_slot_info[2] = {
|
||||||
{
|
{
|
||||||
.clk = PERIPHS_IO_MUX_SD_CLK_U,
|
.clk_gpio = 6,
|
||||||
.cmd = PERIPHS_IO_MUX_SD_CMD_U,
|
.cmd_gpio = 11,
|
||||||
.d0 = PERIPHS_IO_MUX_SD_DATA0_U,
|
.d0_gpio = 7,
|
||||||
.d1 = PERIPHS_IO_MUX_SD_DATA1_U,
|
|
||||||
.d2 = PERIPHS_IO_MUX_SD_DATA2_U,
|
|
||||||
.d3 = PERIPHS_IO_MUX_SD_DATA3_U,
|
|
||||||
.d1_gpio = 8,
|
.d1_gpio = 8,
|
||||||
|
.d2_gpio = 9,
|
||||||
.d3_gpio = 10,
|
.d3_gpio = 10,
|
||||||
.d4 = PERIPHS_IO_MUX_GPIO16_U,
|
.d4_gpio = 16,
|
||||||
.d5 = PERIPHS_IO_MUX_GPIO17_U,
|
.d5_gpio = 17,
|
||||||
.d6 = PERIPHS_IO_MUX_GPIO5_U,
|
.d6_gpio = 5,
|
||||||
.d7 = PERIPHS_IO_MUX_GPIO18_U,
|
.d7_gpio = 18,
|
||||||
.card_detect = HOST_CARD_DETECT_N_1_IDX,
|
.card_detect = HOST_CARD_DETECT_N_1_IDX,
|
||||||
.write_protect = HOST_CARD_WRITE_PRT_1_IDX,
|
.write_protect = HOST_CARD_WRITE_PRT_1_IDX,
|
||||||
.card_int = HOST_CARD_INT_N_1_IDX,
|
.card_int = HOST_CARD_INT_N_1_IDX,
|
||||||
.width = 8
|
.width = 8
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.clk = PERIPHS_IO_MUX_MTMS_U,
|
.clk_gpio = 14,
|
||||||
.cmd = PERIPHS_IO_MUX_MTDO_U,
|
.cmd_gpio = 15,
|
||||||
.d0 = PERIPHS_IO_MUX_GPIO2_U,
|
.d0_gpio = 2,
|
||||||
.d1 = PERIPHS_IO_MUX_GPIO4_U,
|
|
||||||
.d2 = PERIPHS_IO_MUX_MTDI_U,
|
|
||||||
.d3 = PERIPHS_IO_MUX_MTCK_U,
|
|
||||||
.d1_gpio = 4,
|
.d1_gpio = 4,
|
||||||
|
.d2_gpio = 12,
|
||||||
.d3_gpio = 13,
|
.d3_gpio = 13,
|
||||||
|
.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,
|
.card_detect = HOST_CARD_DETECT_N_2_IDX,
|
||||||
.write_protect = HOST_CARD_WRITE_PRT_2_IDX,
|
.write_protect = HOST_CARD_WRITE_PRT_2_IDX,
|
||||||
.card_int = HOST_CARD_INT_N_2_IDX,
|
.card_int = HOST_CARD_INT_N_2_IDX,
|
||||||
|
@ -340,14 +338,18 @@ esp_err_t sdmmc_host_init()
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void configure_pin(int pin)
|
||||||
static inline void configure_pin(uint32_t io_mux_reg)
|
|
||||||
{
|
{
|
||||||
const int sdmmc_func = 3;
|
const int sdmmc_func = 3;
|
||||||
const int drive_strength = 3;
|
const int drive_strength = 3;
|
||||||
PIN_INPUT_ENABLE(io_mux_reg);
|
assert(pin!=-1);
|
||||||
PIN_FUNC_SELECT(io_mux_reg, sdmmc_func);
|
gpio_pulldown_dis(pin);
|
||||||
PIN_SET_DRV(io_mux_reg, drive_strength);
|
|
||||||
|
uint32_t reg = GPIO_PIN_MUX_REG[pin];
|
||||||
|
assert(reg != 0);
|
||||||
|
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)
|
esp_err_t sdmmc_host_init_slot(int slot, const sdmmc_slot_config_t* slot_config)
|
||||||
|
@ -376,13 +378,13 @@ esp_err_t sdmmc_host_init_slot(int slot, const sdmmc_slot_config_t* slot_config)
|
||||||
}
|
}
|
||||||
s_slot_width[slot] = slot_width;
|
s_slot_width[slot] = slot_width;
|
||||||
|
|
||||||
configure_pin(pslot->clk);
|
configure_pin(pslot->clk_gpio);
|
||||||
configure_pin(pslot->cmd);
|
configure_pin(pslot->cmd_gpio);
|
||||||
configure_pin(pslot->d0);
|
configure_pin(pslot->d0_gpio);
|
||||||
|
|
||||||
if (slot_width >= 4) {
|
if (slot_width >= 4) {
|
||||||
configure_pin(pslot->d1);
|
configure_pin(pslot->d1_gpio);
|
||||||
configure_pin(pslot->d2);
|
configure_pin(pslot->d2_gpio);
|
||||||
//force pull-up D3 to make slave detect SD mode. connect to peripheral after width configuration.
|
//force pull-up D3 to make slave detect SD mode. connect to peripheral after width configuration.
|
||||||
gpio_config_t gpio_conf = {
|
gpio_config_t gpio_conf = {
|
||||||
.pin_bit_mask = BIT(pslot->d3_gpio),
|
.pin_bit_mask = BIT(pslot->d3_gpio),
|
||||||
|
@ -394,10 +396,10 @@ esp_err_t sdmmc_host_init_slot(int slot, const sdmmc_slot_config_t* slot_config)
|
||||||
gpio_config( &gpio_conf );
|
gpio_config( &gpio_conf );
|
||||||
gpio_set_level( pslot->d3_gpio, 1 );
|
gpio_set_level( pslot->d3_gpio, 1 );
|
||||||
if (slot_width == 8) {
|
if (slot_width == 8) {
|
||||||
configure_pin(pslot->d4);
|
configure_pin(pslot->d4_gpio);
|
||||||
configure_pin(pslot->d5);
|
configure_pin(pslot->d5_gpio);
|
||||||
configure_pin(pslot->d6);
|
configure_pin(pslot->d6_gpio);
|
||||||
configure_pin(pslot->d7);
|
configure_pin(pslot->d7_gpio);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -492,10 +494,10 @@ esp_err_t sdmmc_host_set_bus_width(int slot, size_t width)
|
||||||
} else if (width == 4) {
|
} else if (width == 4) {
|
||||||
SDMMC.ctype.card_width_8 &= ~mask;
|
SDMMC.ctype.card_width_8 &= ~mask;
|
||||||
SDMMC.ctype.card_width |= 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(s_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){
|
} else if (width == 8){
|
||||||
SDMMC.ctype.card_width_8 |= mask;
|
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(s_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 {
|
} else {
|
||||||
return ESP_ERR_INVALID_ARG;
|
return ESP_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
@ -550,7 +552,7 @@ void sdmmc_host_dma_resume()
|
||||||
|
|
||||||
esp_err_t sdmmc_host_io_int_enable(int slot)
|
esp_err_t sdmmc_host_io_int_enable(int slot)
|
||||||
{
|
{
|
||||||
configure_pin(s_slot_info[slot].d1);
|
configure_pin(s_slot_info[slot].d1_gpio);
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue