From 85ab4fc83e05f04f33324a7a1a51263eaaeeb926 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Mon, 23 Apr 2018 14:44:46 +0800 Subject: [PATCH] sdmmc host: add handling of CD and WP pins Previous version of the code only connected CD and WP to the peripheral, in fact the hardware does not use the values of these signals automatically. This adds code to read CD and WP values when command is executed and return errors if card is not present, or write command is executed when WP signal is active. --- components/driver/sdmmc_host.c | 44 ++++++++++++++----- .../soc/esp32/include/soc/sdmmc_struct.h | 4 +- 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/components/driver/sdmmc_host.c b/components/driver/sdmmc_host.c index f09d94d58..95cb81fdc 100644 --- a/components/driver/sdmmc_host.c +++ b/components/driver/sdmmc_host.c @@ -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) { diff --git a/components/soc/esp32/include/soc/sdmmc_struct.h b/components/soc/esp32/include/soc/sdmmc_struct.h index 9f3625a3d..7e3c6912e 100644 --- a/components/soc/esp32/include/soc/sdmmc_struct.h +++ b/components/soc/esp32/include/soc/sdmmc_struct.h @@ -255,7 +255,7 @@ typedef volatile struct { union { struct { - uint32_t cards: 2; ///< bit N reads 1 if card N is present + uint32_t cards: 2; ///< bit N reads 0 if card N is present uint32_t reserved: 30; }; uint32_t val; @@ -263,7 +263,7 @@ typedef volatile struct { union { struct { - uint32_t card0: 2; ///< bit N reads 1 if card N is write protected + uint32_t cards: 2; ///< bit N reads 1 if card N is write protected uint32_t reserved: 30; }; uint32_t val;