Merge branch 'bugfix/sdspi_wp_cd_pins' into 'master'

sdmmc, sdspi: fix handling of CD and WP

See merge request idf/esp-idf!2285
This commit is contained in:
Ivan Grokhotkov
2018-04-24 20:53:47 +08:00
9 changed files with 198 additions and 31 deletions

View File

@@ -43,9 +43,9 @@ extern "C" {
.set_card_clk = &sdmmc_host_set_card_clk, \
.do_transaction = &sdmmc_host_do_transaction, \
.deinit = &sdmmc_host_deinit, \
.command_timeout_ms = 0, \
.io_int_enable = sdmmc_host_io_int_enable, \
.io_int_wait = sdmmc_host_io_int_wait, \
.command_timeout_ms = 0, \
}
/**

View File

@@ -40,6 +40,7 @@ extern "C" {
.io_voltage = 3.3f, \
.init = &sdspi_host_init, \
.set_bus_width = NULL, \
.get_bus_width = NULL, \
.set_card_clk = &sdspi_host_set_card_clk, \
.do_transaction = &sdspi_host_do_transaction, \
.deinit = &sdspi_host_deinit, \
@@ -72,8 +73,8 @@ typedef struct {
.gpio_mosi = GPIO_NUM_15, \
.gpio_sck = GPIO_NUM_14, \
.gpio_cs = GPIO_NUM_13, \
.gpio_cd = SDMMC_SLOT_NO_CD, \
.gpio_wp = SDMMC_SLOT_NO_WP, \
.gpio_cd = SDSPI_SLOT_NO_CD, \
.gpio_wp = SDSPI_SLOT_NO_WP, \
.dma_channel = 1 \
}

View File

@@ -255,6 +255,12 @@ esp_err_t sdmmc_host_start_command(int slot, sdmmc_hw_cmd_t cmd, uint32_t arg) {
if (!(slot == 0 || slot == 1)) {
return ESP_ERR_INVALID_ARG;
}
if ((SDMMC.cdetect.cards & BIT(slot)) != 0) {
return ESP_ERR_NOT_FOUND;
}
if (cmd.data_expected && cmd.rw && (SDMMC.wrtprt.cards & BIT(slot)) != 0) {
return ESP_ERR_INVALID_STATE;
}
while (SDMMC.cmd.start_command == 1) {
;
}
@@ -397,18 +403,36 @@ esp_err_t sdmmc_host_init_slot(int slot, const sdmmc_slot_config_t* slot_config)
// SDIO slave interrupt is edge sensitive to ~(int_n | card_int | card_detect)
// set this and card_detect to high to enable sdio interrupt
gpio_matrix_in(GPIO_FUNC_IN_HIGH, pslot->card_int, 0);
if (gpio_cd != -1) {
gpio_set_direction(gpio_cd, GPIO_MODE_INPUT);
gpio_matrix_in(gpio_cd, pslot->card_detect, 0);
} else {
gpio_matrix_in(GPIO_FUNC_IN_HIGH, pslot->card_detect, 0);
}
gpio_matrix_in(GPIO_FUNC_IN_HIGH, pslot->card_int, false);
if (gpio_wp != -1) {
gpio_set_direction(gpio_wp, GPIO_MODE_INPUT);
gpio_matrix_in(gpio_wp, pslot->write_protect, 0);
// Set up Card Detect input
int matrix_in_cd;
if (gpio_cd != SDMMC_SLOT_NO_CD) {
ESP_LOGD(TAG, "using GPIO%d as CD pin", gpio_cd);
gpio_pad_select_gpio(gpio_cd);
gpio_set_direction(gpio_cd, GPIO_MODE_INPUT);
matrix_in_cd = gpio_cd;
} else {
// if not set, default to CD low (card present)
matrix_in_cd = GPIO_FUNC_IN_LOW;
}
gpio_matrix_in(matrix_in_cd, pslot->card_detect, false);
// Set up Write Protect input
int matrix_in_wp;
if (gpio_wp != SDMMC_SLOT_NO_WP) {
ESP_LOGD(TAG, "using GPIO%d as WP pin", gpio_wp);
gpio_pad_select_gpio(gpio_wp);
gpio_set_direction(gpio_wp, GPIO_MODE_INPUT);
matrix_in_wp = gpio_wp;
} else {
// if not set, default to WP high (not write protected)
matrix_in_wp = GPIO_FUNC_IN_HIGH;
}
// WP signal is normally active low, but hardware expects
// an active-high signal, so invert it in GPIO matrix
gpio_matrix_in(matrix_in_wp, pslot->write_protect, true);
// By default, set probing frequency (400kHz) and 1-bit bus
esp_err_t ret = sdmmc_host_set_card_clk(slot, 400);
if (ret != ESP_OK) {

View File

@@ -112,6 +112,7 @@ void sdmmc_host_transaction_handler_deinit()
esp_err_t sdmmc_host_do_transaction(int slot, sdmmc_command_t* cmdinfo)
{
esp_err_t ret;
xSemaphoreTake(s_request_mutex, portMAX_DELAY);
#ifdef CONFIG_PM_ENABLE
esp_pm_lock_acquire(s_pm_lock);
@@ -124,12 +125,14 @@ esp_err_t sdmmc_host_do_transaction(int slot, sdmmc_command_t* cmdinfo)
if (cmdinfo->datalen < 4 || cmdinfo->blklen % 4 != 0) {
ESP_LOGD(TAG, "%s: invalid size: total=%d block=%d",
__func__, cmdinfo->datalen, cmdinfo->blklen);
return ESP_ERR_INVALID_SIZE;
ret = ESP_ERR_INVALID_SIZE;
goto out;
}
if ((intptr_t) cmdinfo->data % 4 != 0 ||
!esp_ptr_dma_capable(cmdinfo->data)) {
ESP_LOGD(TAG, "%s: buffer %p can not be used for DMA", __func__, cmdinfo->data);
return ESP_ERR_INVALID_ARG;
ret = ESP_ERR_INVALID_ARG;
goto out;
}
// this clears "owned by IDMAC" bits
memset(s_dma_desc, 0, sizeof(s_dma_desc));
@@ -146,10 +149,9 @@ esp_err_t sdmmc_host_do_transaction(int slot, sdmmc_command_t* cmdinfo)
sdmmc_host_dma_prepare(&s_dma_desc[0], cmdinfo->blklen, cmdinfo->datalen);
}
// write command into hardware, this also sends the command to the card
esp_err_t ret = sdmmc_host_start_command(slot, hw_cmd, cmdinfo->arg);
ret = sdmmc_host_start_command(slot, hw_cmd, cmdinfo->arg);
if (ret != ESP_OK) {
xSemaphoreGive(s_request_mutex);
return ret;
goto out;
}
// process events until transfer is complete
cmdinfo->error = ESP_OK;
@@ -161,6 +163,8 @@ esp_err_t sdmmc_host_do_transaction(int slot, sdmmc_command_t* cmdinfo)
}
}
s_is_app_cmd = (ret == ESP_OK && cmdinfo->opcode == MMC_APP_CMD);
out:
#ifdef CONFIG_PM_ENABLE
esp_pm_lock_release(s_pm_lock);
#endif

View File

@@ -310,22 +310,22 @@ esp_err_t sdspi_host_init_slot(int slot, const sdspi_slot_config_t* slot_config)
// Configure CD and WP pins
io_conf = (gpio_config_t) {
.intr_type = GPIO_PIN_INTR_DISABLE,
.mode = GPIO_MODE_OUTPUT,
.mode = GPIO_MODE_INPUT,
.pin_bit_mask = 0,
.pull_up_en = true
};
if (slot_config->gpio_cd != SDSPI_SLOT_NO_CD) {
io_conf.pin_bit_mask |= (1 << slot_config->gpio_cd);
s_slots[slot].gpio_wp = slot_config->gpio_wp;
s_slots[slot].gpio_cd = slot_config->gpio_cd;
} else {
s_slots[slot].gpio_wp = GPIO_UNUSED;
s_slots[slot].gpio_cd = GPIO_UNUSED;
}
if (slot_config->gpio_wp != SDSPI_SLOT_NO_WP) {
io_conf.pin_bit_mask |= (1 << slot_config->gpio_wp);
s_slots[slot].gpio_cd = slot_config->gpio_cd;
s_slots[slot].gpio_wp = slot_config->gpio_wp;
} else {
s_slots[slot].gpio_cd = GPIO_UNUSED;
s_slots[slot].gpio_wp = GPIO_UNUSED;
}
if (io_conf.pin_bit_mask != 0) {

View File

@@ -0,0 +1,20 @@
#include "driver/sdmmc_host.h"
#include "driver/sdspi_host.h"
/**
* Check that C-style designated initializers are valid in C++ file.
*/
static void test_initializers() __attribute__((unused));
static void test_initializers()
{
sdmmc_host_t sdmmc_host = SDMMC_HOST_DEFAULT();
(void) sdmmc_host;
sdmmc_slot_config_t sdmmc_slot = SDMMC_SLOT_CONFIG_DEFAULT();
(void) sdmmc_slot;
sdmmc_host_t sdspi_host = SDSPI_HOST_DEFAULT();
(void) sdspi_host;
sdspi_slot_config_t sdspi_slot = SDSPI_SLOT_CONFIG_DEFAULT();
(void) sdspi_slot;
}