Skip to content

Commit 7e870ae

Browse files
committed
Merge branch 'bugfix/sdmmc_line_control' into 'master'
bugfix(sdmmc_host): fix some issue with bit width config . See merge request idf/esp-idf!1900
2 parents 75f564d + 2551a73 commit 7e870ae

File tree

5 files changed

+77
-4
lines changed

5 files changed

+77
-4
lines changed

components/driver/include/driver/sdmmc_host.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ extern "C" {
3939
.io_voltage = 3.3f, \
4040
.init = &sdmmc_host_init, \
4141
.set_bus_width = &sdmmc_host_set_bus_width, \
42+
.get_bus_width = &sdmmc_host_get_slot_width, \
4243
.set_card_clk = &sdmmc_host_set_card_clk, \
4344
.do_transaction = &sdmmc_host_do_transaction, \
4445
.deinit = &sdmmc_host_deinit, \
@@ -115,6 +116,14 @@ esp_err_t sdmmc_host_init_slot(int slot, const sdmmc_slot_config_t* slot_config)
115116
*/
116117
esp_err_t sdmmc_host_set_bus_width(int slot, size_t width);
117118

119+
/**
120+
* @brief Get bus width configured in ``sdmmc_host_init_slot`` to be used for data transfer
121+
*
122+
* @param slot slot number (SDMMC_HOST_SLOT_0 or SDMMC_HOST_SLOT_1)
123+
* @return configured bus width of the specified slot.
124+
*/
125+
size_t sdmmc_host_get_slot_width(int slot);
126+
118127
/**
119128
* @brief Set card clock frequency
120129
*

components/driver/include/driver/sdmmc_types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ typedef struct {
125125
float io_voltage; /*!< I/O voltage used by the controller (voltage switching is not supported) */
126126
esp_err_t (*init)(void); /*!< Host function to initialize the driver */
127127
esp_err_t (*set_bus_width)(int slot, size_t width); /*!< host function to set bus width */
128+
size_t (*get_bus_width)(int slot); /*!< host function to get bus width */
128129
esp_err_t (*set_card_clk)(int slot, uint32_t freq_khz); /*!< host function to set card clock frequency */
129130
esp_err_t (*do_transaction)(int slot, sdmmc_command_t* cmdinfo); /*!< host function to do a transaction */
130131
esp_err_t (*deinit)(void); /*!< host function to deinitialize the driver */

components/driver/sdmmc_host.c

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ typedef struct {
4040
uint32_t d5;
4141
uint32_t d6;
4242
uint32_t d7;
43+
uint8_t d3_gpio;
4344
uint8_t card_detect;
4445
uint8_t write_protect;
4546
uint8_t width;
@@ -57,6 +58,7 @@ static const sdmmc_slot_info_t s_slot_info[2] = {
5758
.d1 = PERIPHS_IO_MUX_SD_DATA1_U,
5859
.d2 = PERIPHS_IO_MUX_SD_DATA2_U,
5960
.d3 = PERIPHS_IO_MUX_SD_DATA3_U,
61+
.d3_gpio = 10,
6062
.d4 = PERIPHS_IO_MUX_GPIO16_U,
6163
.d5 = PERIPHS_IO_MUX_GPIO17_U,
6264
.d6 = PERIPHS_IO_MUX_GPIO5_U,
@@ -72,6 +74,7 @@ static const sdmmc_slot_info_t s_slot_info[2] = {
7274
.d1 = PERIPHS_IO_MUX_GPIO4_U,
7375
.d2 = PERIPHS_IO_MUX_MTDI_U,
7476
.d3 = PERIPHS_IO_MUX_MTCK_U,
77+
.d3_gpio = 13,
7578
.card_detect = HOST_CARD_DETECT_N_2_IDX,
7679
.write_protect = HOST_CARD_WRITE_PRT_2_IDX,
7780
.width = 4
@@ -82,6 +85,7 @@ static const char* TAG = "sdmmc_periph";
8285
static intr_handle_t s_intr_handle;
8386
static QueueHandle_t s_event_queue;
8487

88+
size_t s_slot_width[2] = {1,1};
8589

8690
void sdmmc_host_reset()
8791
{
@@ -324,14 +328,25 @@ esp_err_t sdmmc_host_init_slot(int slot, const sdmmc_slot_config_t* slot_config)
324328
else if (slot_width > pslot->width) {
325329
return ESP_ERR_INVALID_ARG;
326330
}
331+
s_slot_width[slot] = slot_width;
327332

328333
configure_pin(pslot->clk);
329334
configure_pin(pslot->cmd);
330335
configure_pin(pslot->d0);
336+
331337
if (slot_width >= 4) {
332338
configure_pin(pslot->d1);
333339
configure_pin(pslot->d2);
334-
configure_pin(pslot->d3);
340+
//force pull-up D3 to make slave detect SD mode. connect to peripheral after width configuration.
341+
gpio_config_t gpio_conf = {
342+
.pin_bit_mask = BIT(pslot->d3_gpio),
343+
.mode = GPIO_MODE_OUTPUT ,
344+
.pull_up_en = 0,
345+
.pull_down_en = 0,
346+
.intr_type = GPIO_INTR_DISABLE,
347+
};
348+
gpio_config( &gpio_conf );
349+
gpio_set_level( pslot->d3_gpio, 1 );
335350
if (slot_width == 8) {
336351
configure_pin(pslot->d4);
337352
configure_pin(pslot->d5);
@@ -404,15 +419,23 @@ esp_err_t sdmmc_host_set_bus_width(int slot, size_t width)
404419
} else if (width == 4) {
405420
SDMMC.ctype.card_width_8 &= ~mask;
406421
SDMMC.ctype.card_width |= mask;
422+
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
407423
} else if (width == 8){
408424
SDMMC.ctype.card_width_8 |= mask;
425+
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
409426
} else {
410427
return ESP_ERR_INVALID_ARG;
411428
}
412429
ESP_LOGD(TAG, "slot=%d width=%d", slot, width);
413430
return ESP_OK;
414431
}
415432

433+
size_t sdmmc_host_get_slot_width(int slot)
434+
{
435+
assert( slot == 0 || slot == 1 );
436+
return s_slot_width[slot];
437+
}
438+
416439
static void sdmmc_host_dma_init()
417440
{
418441
SDMMC.ctrl.dma_enable = 1;

components/sdmmc/sdmmc_cmd.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,17 @@ esp_err_t sdmmc_card_init(const sdmmc_host_t* config, sdmmc_card_t* card)
8282
memcpy(&card->host, config, sizeof(*config));
8383
const bool is_spi = host_is_spi(card);
8484

85+
if ( !is_spi ) {
86+
//check HOST flags compatible with slot configuration.
87+
int slot_bit_width = config->get_bus_width(config->slot);
88+
if ( slot_bit_width == 1 && (config->flags & (SDMMC_HOST_FLAG_4BIT|SDMMC_HOST_FLAG_8BIT))) {
89+
ESP_LOGW(TAG, "HOST slot only enables 1-bit.");
90+
card->host.flags = ((card->host.flags&(~(SDMMC_HOST_FLAG_4BIT|SDMMC_HOST_FLAG_8BIT)))|SDMMC_HOST_FLAG_1BIT);
91+
} else if ( slot_bit_width == 4 && (config->flags & SDMMC_HOST_FLAG_8BIT)){
92+
ESP_LOGW(TAG, "HOST slot only enables 4-bit.");
93+
card->host.flags = ((card->host.flags&(~(SDMMC_HOST_FLAG_1BIT|SDMMC_HOST_FLAG_8BIT)))|SDMMC_HOST_FLAG_4BIT);
94+
}
95+
}
8596
/* GO_IDLE_STATE (CMD0) command resets the card */
8697
esp_err_t err = sdmmc_send_cmd_go_idle_state(card);
8798
if (err != ESP_OK) {
@@ -218,7 +229,7 @@ esp_err_t sdmmc_card_init(const sdmmc_host_t* config, sdmmc_card_t* card)
218229
/* If the host has been initialized with 4-bit bus support, and the card
219230
* supports 4-bit bus, switch to 4-bit bus now.
220231
*/
221-
if ((config->flags & SDMMC_HOST_FLAG_4BIT) &&
232+
if ((card->host.flags & SDMMC_HOST_FLAG_4BIT) &&
222233
(card->scr.bus_width & SCR_SD_BUS_WIDTHS_4BIT)) {
223234
ESP_LOGD(TAG, "switching to 4-bit bus mode");
224235
err = sdmmc_send_cmd_set_bus_width(card, 4);

components/sdmmc/test/test_sd.c

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ TEST_CASE("MMC_RSP_BITS", "[sd]")
3636
TEST_ASSERT_EQUAL_HEX32(0x11, MMC_RSP_BITS(data, 59, 5));
3737
}
3838

39-
TEST_CASE("can probe SD", "[sd][test_env=UT_T1_SDMODE][ignore]")
39+
TEST_CASE("can probe SD (4-bit)", "[sd][test_env=UT_T1_SDMODE]")
4040
{
4141
sdmmc_host_t config = SDMMC_HOST_DEFAULT();
4242
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
@@ -50,8 +50,37 @@ TEST_CASE("can probe SD", "[sd][test_env=UT_T1_SDMODE][ignore]")
5050
free(card);
5151
}
5252

53+
TEST_CASE("can probe SD (1-bit)", "[sd][test_env=UT_T1_SDMODE]")
54+
{
55+
//the card DAT3 should be connected to high in SD 1-bit mode
56+
//do it by our own GPIO.
57+
gpio_config_t conf = {
58+
.pin_bit_mask = GPIO_SEL_13,
59+
.mode = GPIO_MODE_OUTPUT,
60+
.pull_up_en = 1,
61+
.pull_down_en = 0,
62+
.intr_type = GPIO_INTR_DISABLE,
63+
};
64+
gpio_config(&conf);
65+
gpio_set_level(GPIO_NUM_13, 1);
66+
67+
sdmmc_host_t config = SDMMC_HOST_DEFAULT();
68+
config.flags = SDMMC_HOST_FLAG_1BIT;
69+
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
70+
slot_config.width=1;
71+
TEST_ESP_OK(sdmmc_host_init());
72+
TEST_ESP_OK(sdmmc_host_init_slot(SDMMC_HOST_SLOT_1, &slot_config));
73+
sdmmc_card_t* card = malloc(sizeof(sdmmc_card_t));
74+
TEST_ASSERT_NOT_NULL(card);
75+
TEST_ESP_OK(sdmmc_card_init(&config, card));
76+
sdmmc_card_print_info(stdout, card);
77+
TEST_ESP_OK(sdmmc_host_deinit());
78+
free(card);
79+
}
80+
81+
5382

54-
TEST_CASE("can probe SD(using SPI)", "[sdspi][test_env=UT_T1_SPIMODE][ignore]")
83+
TEST_CASE("can probe SD(using SPI)", "[sdspi][test_env=UT_T1_SPIMODE]")
5584
{
5685
sdmmc_host_t config = SDSPI_HOST_DEFAULT();
5786
sdspi_slot_config_t slot_config = SDSPI_SLOT_CONFIG_DEFAULT();

0 commit comments

Comments
 (0)