From 54647dbbd3b32799cdce74ec7094bf259ed9611b Mon Sep 17 00:00:00 2001 From: "sonika.rathi" Date: Mon, 27 Nov 2023 11:13:48 +0100 Subject: [PATCH] feat(sd_card): add built-in checks for connections to the card and correct pullups --- examples/storage/sd_card/sdmmc/CMakeLists.txt | 3 + examples/storage/sd_card/sdmmc/README.md | 69 ++++++ .../sdmmc/components/sd_card/CMakeLists.txt | 4 + .../sdmmc/components/sd_card/sd_test_io.c | 231 ++++++++++++++++++ .../sdmmc/components/sd_card/sd_test_io.h | 28 +++ .../storage/sd_card/sdmmc/main/CMakeLists.txt | 7 +- .../sd_card/sdmmc/main/Kconfig.projbuild | 86 +++++++ .../sd_card/sdmmc/main/sd_card_example_main.c | 38 +++ examples/storage/sd_card/sdspi/CMakeLists.txt | 3 + examples/storage/sd_card/sdspi/README.md | 56 +++++ .../storage/sd_card/sdspi/main/CMakeLists.txt | 8 +- .../sd_card/sdspi/main/Kconfig.projbuild | 45 ++++ .../sd_card/sdspi/main/sd_card_example_main.c | 28 +++ 13 files changed, 602 insertions(+), 4 deletions(-) create mode 100644 examples/storage/sd_card/sdmmc/components/sd_card/CMakeLists.txt create mode 100644 examples/storage/sd_card/sdmmc/components/sd_card/sd_test_io.c create mode 100644 examples/storage/sd_card/sdmmc/components/sd_card/sd_test_io.h diff --git a/examples/storage/sd_card/sdmmc/CMakeLists.txt b/examples/storage/sd_card/sdmmc/CMakeLists.txt index 0f0353e3e3..d9424b30f4 100644 --- a/examples/storage/sd_card/sdmmc/CMakeLists.txt +++ b/examples/storage/sd_card/sdmmc/CMakeLists.txt @@ -3,4 +3,7 @@ cmake_minimum_required(VERSION 3.16) include($ENV{IDF_PATH}/tools/cmake/project.cmake) + +set(COMPONENTS main) + project(sd_card) diff --git a/examples/storage/sd_card/sdmmc/README.md b/examples/storage/sd_card/sdmmc/README.md index 9f29c07d60..8c4c8ad7a3 100644 --- a/examples/storage/sd_card/sdmmc/README.md +++ b/examples/storage/sd_card/sdmmc/README.md @@ -182,3 +182,72 @@ Connections between the card and the ESP32 are too long for the frequency used. example: Failed to mount filesystem. If you want the card to be formatted, set the EXAMPLE_FORMAT_IF_MOUNT_FAILED menuconfig option. ``` The example will be able to mount only cards formatted using FAT32 filesystem. If the card is formatted as exFAT or some other filesystem, you have an option to format it in the example code. Enable the `EXAMPLE_FORMAT_IF_MOUNT_FAILED` menuconfig option, then build and flash the example. + +### Debug SD connections and pullup strength + +> If the initialization of the SD card fails, initially follow the above options. If the issue persists, confirm the connection of pullups to the SD pins. To do this, enable the` Debug sd pin connections and pullup strength` option from menuconfig and rerun the code. This will provide the following result: + +``` +**** PIN recovery time **** + +PIN 14 CLK 10044 cycles +PIN 15 CMD 10034 cycles +PIN 2 D0 10034 cycles +PIN 4 D1 10034 cycles +PIN 12 D2 10034 cycles +PIN 13 D3 10034 cycles + +**** PIN recovery time with weak pullup **** + +PIN 14 CLK 100 cycles +PIN 15 CMD 100 cycles +PIN 2 D0 100 cycles +PIN 4 D1 100 cycles +PIN 12 D2 100 cycles +PIN 13 D3 100 cycles + +**** PIN voltage levels **** + +PIN 14 CLK 0.6V +PIN 15 CMD 0.3V +PIN 2 D0 0.8V +PIN 4 D1 0.6V +PIN 12 D2 0.4V +PIN 13 D3 0.8V + +**** PIN voltage levels with weak pullup **** + +PIN 14 CLK 1.0V +PIN 15 CMD 1.1V +PIN 2 D0 1.0V +PIN 4 D1 1.0V +PIN 12 D2 1.0V +PIN 13 D3 1.2V + +**** PIN cross-talk **** + + CLK CMD D0 D1 D2 D3 +PIN 14 CLK -- 0.2V 0.1V 0.1V 0.1V 0.2V +PIN 15 CMD 0.1V -- 0.1V 0.1V 0.1V 0.1V +PIN 2 D0 0.1V 0.1V -- 0.2V 0.1V 0.1V +PIN 4 D1 0.1V 0.1V 0.3V -- 0.1V 0.1V +PIN 12 D2 0.1V 0.2V 0.2V 0.1V -- 0.1V +PIN 13 D3 0.1V 0.2V 0.1V 0.1V 0.1V -- + +**** PIN cross-talk with weak pullup **** + + CLK CMD D0 D1 D2 D3 +PIN 14 CLK -- 1.0V 1.0V 1.0V 1.0V 1.2V +PIN 15 CMD 0.9V -- 1.0V 1.0V 1.0V 1.2V +PIN 2 D0 0.9V 1.0V -- 1.0V 1.0V 1.2V +PIN 4 D1 0.9V 1.0V 1.2V -- 1.0V 1.2V +PIN 12 D2 0.9V 1.1V 1.2V 0.9V -- 1.2V +PIN 13 D3 0.9V 1.2V 1.1V 0.9V 0.9V -- +I (845) main_task: Returned from app_main() +``` + +In the absence of connected pullups and having the weak pullups enabled, you can assess the pullup connections by comparing PIN recovery time measured in CPU cycles. To check pullup connections, configure the pin as open drain, set it to low state, and count the cpu cycles consumed before returning to high state. If a pullup is connected, the pin will get back to high state after reasonably small cycle count, typically around 50-300 cycles, depending on pullup strength. If no pullup is connected, the PIN stays low and the measurement times out after 10000 cycles. + +It will also provide the voltage levels at the corresponding SD pins. By default, this information is provided for ESP32 chip only, and for other chipsets, verify the availability of ADC pins for the respective GPIO using [this](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/gpio.html#gpio-summary) and configure ADC mapped pins using menuconfig. Then test the voltage levels accordingly. + +You can monitor the voltage levels of individual pins using `PIN voltage levels` and `PIN voltage levels with weak pullup`. However, if one pin being pulled low and experiencing interference with another pin, you can detect it through `PIN cross-talk` and `PIN cross-talk with weak pullup`. In the absence of pullups, voltage levels at each pin should range from 0 to 0.3V. With 10k pullups connected, the voltage will be between 3.1V to 3.3V, contingent on the connection between ADC pins and SD pins, and with weak pullups connected, it can fluctuate between 0.8V to 1.2V, depending on pullup strength. \ No newline at end of file diff --git a/examples/storage/sd_card/sdmmc/components/sd_card/CMakeLists.txt b/examples/storage/sd_card/sdmmc/components/sd_card/CMakeLists.txt new file mode 100644 index 0000000000..c5900560b6 --- /dev/null +++ b/examples/storage/sd_card/sdmmc/components/sd_card/CMakeLists.txt @@ -0,0 +1,4 @@ +idf_component_register(SRCS "sd_test_io.c" + INCLUDE_DIRS "." + REQUIRES fatfs esp_adc + WHOLE_ARCHIVE) diff --git a/examples/storage/sd_card/sdmmc/components/sd_card/sd_test_io.c b/examples/storage/sd_card/sdmmc/components/sd_card/sd_test_io.c new file mode 100644 index 0000000000..ade527b854 --- /dev/null +++ b/examples/storage/sd_card/sdmmc/components/sd_card/sd_test_io.c @@ -0,0 +1,231 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include +#include +#include +#include "esp_adc/adc_oneshot.h" +#include "driver/gpio.h" +#include "esp_cpu.h" +#include "esp_log.h" +#include "sd_test_io.h" + +const static char *TAG = "SD_TEST"; + +#define ADC_ATTEN_DB ADC_ATTEN_DB_12 +#define GPIO_INPUT_PIN_SEL(pin) (1ULL<pins[i]); + io_conf.pull_down_en = 0; + io_conf.pull_up_en = 0; + gpio_config(&io_conf); + } + + printf("\n**** PIN recovery time ****\n\n"); + + for (int i = 0; i < pin_count; ++i) { + gpio_set_direction(config->pins[i], GPIO_MODE_INPUT_OUTPUT_OD); + gpio_set_level(config->pins[i], 0); + usleep(100); + gpio_set_level(config->pins[i], 1); + uint32_t cycles = get_cycles_until_pin_level(config->pins[i], 1, 10000); + printf("PIN %2d %3s %"PRIu32" cycles\n", config->pins[i], config->names[i], cycles); + } + + printf("\n**** PIN recovery time with weak pullup ****\n\n"); + + for (int i = 0; i < pin_count; ++i) { + gpio_set_direction(config->pins[i], GPIO_MODE_INPUT_OUTPUT_OD); + gpio_pullup_en(config->pins[i]); + gpio_set_level(config->pins[i], 0); + usleep(100); + gpio_set_level(config->pins[i], 1); + uint32_t cycles = get_cycles_until_pin_level(config->pins[i], 1, 10000); + printf("PIN %2d %3s %"PRIu32" cycles\n", config->pins[i], config->names[i], cycles); + gpio_pullup_dis(config->pins[i]); + } + +#if CONFIG_EXAMPLE_ENABLE_ADC_FEATURE + + adc_oneshot_unit_handle_t adc_handle; + adc_oneshot_unit_init_cfg_t init_config = { + .unit_id = CONFIG_EXAMPLE_ADC_UNIT, + }; + ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config, &adc_handle)); + + adc_cali_handle_t *adc_cali_handle = (adc_cali_handle_t *)malloc(sizeof(adc_cali_handle_t)*pin_count); + bool *do_calibration = (bool *)malloc(sizeof(bool)*pin_count); + + for (int i = 0; i < pin_count; i++) { + do_calibration[i] = adc_calibration_init(CONFIG_EXAMPLE_ADC_UNIT, i, ADC_ATTEN_DB, &adc_cali_handle[i]); + } + + printf("\n**** PIN voltage levels ****\n\n"); + + for (int i = 0; i < pin_count; ++i) { + float voltage = get_pin_voltage(config->adc_channels[i], adc_handle, do_calibration[i], adc_cali_handle[i]); + printf("PIN %2d %3s %.1fV\n", config->pins[i], config->names[i], voltage); + } + + printf("\n**** PIN voltage levels with weak pullup ****\n\n"); + + for (int i = 0; i < pin_count; ++i) { + gpio_pullup_en(config->pins[i]); + usleep(100); + float voltage = get_pin_voltage(config->adc_channels[i], adc_handle, do_calibration[i], adc_cali_handle[i]); + printf("PIN %2d %3s %.1fV\n", config->pins[i], config->names[i], voltage); + gpio_pullup_dis(config->pins[i]); + } + + printf("\n**** PIN cross-talk ****\n\n"); + + printf(" "); + for (int i = 0; i < pin_count; ++i) { + printf("%3s ", config->names[i]); + } + printf("\n"); + for (int i = 0; i < pin_count; ++i) { + gpio_set_direction(config->pins[i], GPIO_MODE_INPUT_OUTPUT_OD); + gpio_set_level(config->pins[i], 0); + printf("PIN %2d %3s ", config->pins[i], config->names[i]); + for (int j = 0; j < pin_count; ++j) { + if (j == i) { + printf(" -- "); + continue; + } + usleep(100); + float voltage = get_pin_voltage(config->adc_channels[j], adc_handle, do_calibration[i], adc_cali_handle[i]); + printf("%1.1fV ", voltage); + } + printf("\n"); + gpio_set_direction(config->pins[i], GPIO_MODE_INPUT); + } + + printf("\n**** PIN cross-talk with weak pullup ****\n\n"); + + printf(" "); + for (int i = 0; i < pin_count; ++i) { + printf("%3s ", config->names[i]); + } + printf("\n"); + for (int i = 0; i < pin_count; ++i) { + gpio_set_direction(config->pins[i], GPIO_MODE_INPUT_OUTPUT_OD); + gpio_set_level(config->pins[i], 0); + printf("PIN %2d %3s ", config->pins[i], config->names[i]); + for (int j = 0; j < pin_count; ++j) { + if (j == i) { + printf(" -- "); + continue; + } + gpio_pullup_en(config->pins[j]); + usleep(100); + float voltage = get_pin_voltage(config->adc_channels[j], adc_handle, do_calibration[i], adc_cali_handle[i]); + printf("%1.1fV ", voltage); + gpio_pullup_dis(config->pins[j]); + } + printf("\n"); + gpio_set_direction(config->pins[i], GPIO_MODE_INPUT); + } + + for (int i = 0; i < pin_count; ++i) { + if (do_calibration[i]) { + example_adc_calibration_deinit(adc_cali_handle[i]); + } + } +#endif //CONFIG_EXAMPLE_ENABLE_ADC_FEATURE +} diff --git a/examples/storage/sd_card/sdmmc/components/sd_card/sd_test_io.h b/examples/storage/sd_card/sdmmc/components/sd_card/sd_test_io.h new file mode 100644 index 0000000000..b9c23fc7fe --- /dev/null +++ b/examples/storage/sd_card/sdmmc/components/sd_card/sd_test_io.h @@ -0,0 +1,28 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + const char** names; + const int* pins; +#if CONFIG_EXAMPLE_ENABLE_ADC_FEATURE + const int *adc_channels; +#endif +} pin_configuration_t; + + +void check_sd_card_pins(pin_configuration_t *config, const int pin_count); + +#ifdef __cplusplus +} +#endif diff --git a/examples/storage/sd_card/sdmmc/main/CMakeLists.txt b/examples/storage/sd_card/sdmmc/main/CMakeLists.txt index aaa92955ad..cae1a04464 100644 --- a/examples/storage/sd_card/sdmmc/main/CMakeLists.txt +++ b/examples/storage/sd_card/sdmmc/main/CMakeLists.txt @@ -1,6 +1,9 @@ -idf_component_register(SRCS "sd_card_example_main.c" - INCLUDE_DIRS ".") +set(srcs "sd_card_example_main.c") +idf_component_register(SRCS ${srcs} + INCLUDE_DIRS "." + REQUIRES fatfs sd_card + WHOLE_ARCHIVE) if(NOT CONFIG_SOC_SDMMC_HOST_SUPPORTED) fail_at_build_time(sdmmc "" diff --git a/examples/storage/sd_card/sdmmc/main/Kconfig.projbuild b/examples/storage/sd_card/sdmmc/main/Kconfig.projbuild index 3b4b8bca85..a5ce9e41b0 100644 --- a/examples/storage/sd_card/sdmmc/main/Kconfig.projbuild +++ b/examples/storage/sd_card/sdmmc/main/Kconfig.projbuild @@ -60,4 +60,90 @@ menu "SD/MMC Example Configuration" endif # SOC_SDMMC_USE_GPIO_MATRIX + config EXAMPLE_DEBUG_PIN_CONNECTIONS + bool "Debug sd pin connections and pullup strength" + default n + + if !SOC_SDMMC_USE_GPIO_MATRIX + config EXAMPLE_PIN_CMD + depends on EXAMPLE_DEBUG_PIN_CONNECTIONS + default 15 if IDF_TARGET_ESP32 + + config EXAMPLE_PIN_CLK + depends on EXAMPLE_DEBUG_PIN_CONNECTIONS + default 14 if IDF_TARGET_ESP32 + + config EXAMPLE_PIN_D0 + depends on EXAMPLE_DEBUG_PIN_CONNECTIONS + default 2 if IDF_TARGET_ESP32 + + if EXAMPLE_SDMMC_BUS_WIDTH_4 + + config EXAMPLE_PIN_D1 + depends on EXAMPLE_DEBUG_PIN_CONNECTIONS + default 4 if IDF_TARGET_ESP32 + + config EXAMPLE_PIN_D2 + depends on EXAMPLE_DEBUG_PIN_CONNECTIONS + default 12 if IDF_TARGET_ESP32 + + config EXAMPLE_PIN_D3 + depends on EXAMPLE_DEBUG_PIN_CONNECTIONS + default 13 if IDF_TARGET_ESP32 + + endif # EXAMPLE_SDMMC_BUS_WIDTH_4 + endif + + config EXAMPLE_ENABLE_ADC_FEATURE + bool "Enable ADC feature" + depends on EXAMPLE_DEBUG_PIN_CONNECTIONS + default y if IDF_TARGET_ESP32 + default n + + config EXAMPLE_ADC_UNIT + int "ADC Unit" + depends on EXAMPLE_ENABLE_ADC_FEATURE + default 1 if IDF_TARGET_ESP32 + default 1 + + config EXAMPLE_ADC_PIN_CLK + int "CLK mapped ADC pin" + depends on EXAMPLE_ENABLE_ADC_FEATURE + default 6 if IDF_TARGET_ESP32 + default 1 + + config EXAMPLE_ADC_PIN_CMD + int "CMD mapped ADC pin" + depends on EXAMPLE_ENABLE_ADC_FEATURE + default 3 if IDF_TARGET_ESP32 + default 1 + + config EXAMPLE_ADC_PIN_D0 + int "D0 mapped ADC pin" + depends on EXAMPLE_ENABLE_ADC_FEATURE + default 2 if IDF_TARGET_ESP32 + default 1 + + if EXAMPLE_SDMMC_BUS_WIDTH_4 + + config EXAMPLE_ADC_PIN_D1 + int "D1 mapped ADC pin" + depends on EXAMPLE_ENABLE_ADC_FEATURE + default 0 if IDF_TARGET_ESP32 + default 1 + + config EXAMPLE_ADC_PIN_D2 + int "D2 mapped ADC pin" + depends on EXAMPLE_ENABLE_ADC_FEATURE + default 5 if IDF_TARGET_ESP32 + default 1 + + config EXAMPLE_ADC_PIN_D3 + int "D3 mapped ADC pin" + depends on EXAMPLE_ENABLE_ADC_FEATURE + default 4 if IDF_TARGET_ESP32 + default 1 + + endif # EXAMPLE_SDMMC_BUS_WIDTH_4 + endmenu diff --git a/examples/storage/sd_card/sdmmc/main/sd_card_example_main.c b/examples/storage/sd_card/sdmmc/main/sd_card_example_main.c index 51c169f030..9129353d38 100644 --- a/examples/storage/sd_card/sdmmc/main/sd_card_example_main.c +++ b/examples/storage/sd_card/sdmmc/main/sd_card_example_main.c @@ -14,6 +14,7 @@ #include "esp_vfs_fat.h" #include "sdmmc_cmd.h" #include "driver/sdmmc_host.h" +#include "sd_test_io.h" #define EXAMPLE_MAX_CHAR_SIZE 64 @@ -21,6 +22,40 @@ static const char *TAG = "example"; #define MOUNT_POINT "/sdcard" +#ifdef CONFIG_EXAMPLE_DEBUG_PIN_CONNECTIONS +const char* names[] = {"CLK", "CMD", "D0", "D1", "D2", "D3"}; +const int pins[] = {CONFIG_EXAMPLE_PIN_CLK, + CONFIG_EXAMPLE_PIN_CMD, + CONFIG_EXAMPLE_PIN_D0 + #ifdef CONFIG_EXAMPLE_SDMMC_BUS_WIDTH_4 + ,CONFIG_EXAMPLE_PIN_D1, + CONFIG_EXAMPLE_PIN_D2, + CONFIG_EXAMPLE_PIN_D3 + #endif + }; + +const int pin_count = sizeof(pins)/sizeof(pins[0]); + +#if CONFIG_EXAMPLE_ENABLE_ADC_FEATURE +const int adc_channels[] = {CONFIG_EXAMPLE_ADC_PIN_CLK, + CONFIG_EXAMPLE_ADC_PIN_CMD, + CONFIG_EXAMPLE_ADC_PIN_D0 + #ifdef CONFIG_EXAMPLE_SDMMC_BUS_WIDTH_4 + ,CONFIG_EXAMPLE_ADC_PIN_D1, + CONFIG_EXAMPLE_ADC_PIN_D2, + CONFIG_EXAMPLE_ADC_PIN_D3 + #endif + }; +#endif //CONFIG_EXAMPLE_ENABLE_ADC_FEATURE + +pin_configuration_t config = { + .names = names, + .pins = pins, +#if CONFIG_EXAMPLE_ENABLE_ADC_FEATURE + .adc_channels = adc_channels, +#endif +}; +#endif //CONFIG_EXAMPLE_DEBUG_PIN_CONNECTIONS static esp_err_t s_example_write_file(const char *path, char *data) { @@ -130,6 +165,9 @@ void app_main(void) } else { ESP_LOGE(TAG, "Failed to initialize the card (%s). " "Make sure SD card lines have pull-up resistors in place.", esp_err_to_name(ret)); +#ifdef CONFIG_EXAMPLE_DEBUG_PIN_CONNECTIONS + check_sd_card_pins(&config, pin_count); +#endif } return; } diff --git a/examples/storage/sd_card/sdspi/CMakeLists.txt b/examples/storage/sd_card/sdspi/CMakeLists.txt index 0f0353e3e3..d41a683007 100644 --- a/examples/storage/sd_card/sdspi/CMakeLists.txt +++ b/examples/storage/sd_card/sdspi/CMakeLists.txt @@ -2,5 +2,8 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.16) +list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/examples/storage/sd_card/sdmmc/components/sd_card") +set(COMPONENTS main) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(sd_card) diff --git a/examples/storage/sd_card/sdspi/README.md b/examples/storage/sd_card/sdspi/README.md index c8a223ab11..eb51c1ba08 100644 --- a/examples/storage/sd_card/sdspi/README.md +++ b/examples/storage/sd_card/sdspi/README.md @@ -155,3 +155,59 @@ Ensure that the board and SD card adapter you are using are powered using the ap Attempt to reboot the board. This error may occur if you reset the ESP board or host controller without power-cycling it. In such cases, the card may remain in its previous state, causing it to potentially not respond to commands sent by the host controller. Additionally, if the example works with certain SD cards but encounters issues with others, please confirm the read/write speed of the SD card. If the card is not compatible with the host frequency, consider lowering the host frequency and then attempting the operation again. + +### Debug SD connections and pullup strength + +> If the initialization of the SD card fails, initially follow the above options. If the issue persists, confirm the connection of pullups to the SD pins. To do this, enable the` Debug sd pin connections and pullup strength` option from menuconfig and rerun the code. This will provide the following result: + +``` +**** PIN recovery time **** + +PIN 14 CLK 10049 cycles +PIN 15 MOSI 10034 cycles +PIN 2 MISO 10034 cycles +PIN 13 CS 10034 cycles + +**** PIN recovery time with weak pullup **** + +PIN 14 CLK 100 cycles +PIN 15 MOSI 100 cycles +PIN 2 MISO 100 cycles +PIN 13 CS 100 cycles + +**** PIN voltage levels **** + +PIN 14 CLK 0.6V +PIN 15 MOSI 0.4V +PIN 2 MISO 0.7V +PIN 13 CS 0.9V + +**** PIN voltage levels with weak pullup **** + +PIN 14 CLK 0.9V +PIN 15 MOSI 1.0V +PIN 2 MISO 1.0V +PIN 13 CS 1.2V + +**** PIN cross-talk **** + + CLK MOSI MISO CS +PIN 14 CLK -- 0.2V 0.2V 0.2V +PIN 15 MOSI 0.1V -- 0.1V 0.1V +PIN 2 MISO 0.1V 0.1V -- 0.1V +PIN 13 CS 0.1V 0.1V 0.1V -- + +**** PIN cross-talk with weak pullup **** + + CLK MOSI MISO CS +PIN 14 CLK -- 1.0V 1.1V 1.2V +PIN 15 MOSI 0.9V -- 1.0V 1.2V +PIN 2 MISO 0.9V 1.0V -- 1.2V +PIN 13 CS 0.9V 1.1V 1.0V -- + +``` +In the absence of connected pullups and having the weak pullups enabled, you can assess the pullup connections by comparing PIN recovery time measured in CPU cycles. To check pullup connections, configure the pin as open drain, set it to low state, and count the cpu cycles consumed before returning to high state. If a pullup is connected, the pin will get back to high state after reasonably small cycle count, typically around 50-300 cycles, depending on pullup strength. If no pullup is connected, the PIN stays low and the measurement times out after 10000 cycles. + +It will also provide the voltage levels at the corresponding SD pins. By default, this information is provided for ESP32 chip only, and for other chipsets, verify the availability of ADC pins for the respective GPIO using [this](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/gpio.html#gpio-summary) and configure ADC mapped pins using menuconfig. Then test the voltage levels accordingly. + +You can monitor the voltage levels of individual pins using `PIN voltage levels` and `PIN voltage levels with weak pullup`. However, if one pin being pulled low and experiencing interference with another pin, you can detect it through `PIN cross-talk` and `PIN cross-talk with weak pullup`. In the absence of pullups, voltage levels at each pin should range from 0 to 0.3V. With 10k pullups connected, the voltage will be between 3.1V to 3.3V, contingent on the connection between ADC pins and SD pins, and with weak pullups connected, it can fluctuate between 0.8V to 1.2V, depending on pullup strength. diff --git a/examples/storage/sd_card/sdspi/main/CMakeLists.txt b/examples/storage/sd_card/sdspi/main/CMakeLists.txt index 39630ccc57..c2068734f3 100644 --- a/examples/storage/sd_card/sdspi/main/CMakeLists.txt +++ b/examples/storage/sd_card/sdspi/main/CMakeLists.txt @@ -1,2 +1,6 @@ -idf_component_register(SRCS "sd_card_example_main.c" - INCLUDE_DIRS ".") +set(srcs "sd_card_example_main.c") + +idf_component_register(SRCS ${srcs} + INCLUDE_DIRS "." + REQUIRES fatfs sd_card + WHOLE_ARCHIVE) diff --git a/examples/storage/sd_card/sdspi/main/Kconfig.projbuild b/examples/storage/sd_card/sdspi/main/Kconfig.projbuild index 7aa77e099c..777fc1e8c2 100644 --- a/examples/storage/sd_card/sdspi/main/Kconfig.projbuild +++ b/examples/storage/sd_card/sdspi/main/Kconfig.projbuild @@ -42,4 +42,49 @@ menu "SD SPI Example Configuration" default 10 if IDF_TARGET_ESP32P4 default 1 # C3 and others + config EXAMPLE_DEBUG_PIN_CONNECTIONS + bool "Debug sd pin connections and pullup strength" + default n + + config EXAMPLE_ENABLE_ADC_FEATURE + bool "Enable ADC feature" + depends on EXAMPLE_DEBUG_PIN_CONNECTIONS + default y if IDF_TARGET_ESP32 + default n + + config EXAMPLE_ADC_UNIT + int "ADC Unit" + depends on EXAMPLE_DEBUG_PIN_CONNECTIONS + default 1 if IDF_TARGET_ESP32 + default 0 if IDF_TARGET_ESP32S3 + default 1 + + config EXAMPLE_ADC_PIN_MOSI + int "MOSI mapped ADC pin" + depends on EXAMPLE_ENABLE_ADC_FEATURE + default 3 if IDF_TARGET_ESP32 + default 7 if IDF_TARGET_ESP32S3 + default 1 + + config EXAMPLE_ADC_PIN_MISO + int "MISO mapped ADC pin" + depends on EXAMPLE_ENABLE_ADC_FEATURE + default 2 if IDF_TARGET_ESP32 + default 1 if IDF_TARGET_ESP32S3 + default 1 + + config EXAMPLE_ADC_PIN_CLK + int "CLK mapped ADC pin" + depends on EXAMPLE_ENABLE_ADC_FEATURE + default 6 if IDF_TARGET_ESP32 + default 0 if IDF_TARGET_ESP32S3 + default 1 + + config EXAMPLE_ADC_PIN_CS + int "CS mapped ADC pin" + depends on EXAMPLE_ENABLE_ADC_FEATURE + default 4 if IDF_TARGET_ESP32 + default 6 if IDF_TARGET_ESP32S3 + default 1 + endmenu diff --git a/examples/storage/sd_card/sdspi/main/sd_card_example_main.c b/examples/storage/sd_card/sdspi/main/sd_card_example_main.c index 6b23d7a577..fd8f6953c6 100644 --- a/examples/storage/sd_card/sdspi/main/sd_card_example_main.c +++ b/examples/storage/sd_card/sdspi/main/sd_card_example_main.c @@ -13,6 +13,7 @@ #include #include "esp_vfs_fat.h" #include "sdmmc_cmd.h" +#include "sd_test_io.h" #define EXAMPLE_MAX_CHAR_SIZE 64 @@ -20,6 +21,30 @@ static const char *TAG = "example"; #define MOUNT_POINT "/sdcard" +#ifdef CONFIG_EXAMPLE_DEBUG_PIN_CONNECTIONS +const char* names[] = {"CLK ", "MOSI", "MISO", "CS "}; +const int pins[] = {CONFIG_EXAMPLE_PIN_CLK, + CONFIG_EXAMPLE_PIN_MOSI, + CONFIG_EXAMPLE_PIN_MISO, + CONFIG_EXAMPLE_PIN_CS}; + +const int pin_count = sizeof(pins)/sizeof(pins[0]); +#if CONFIG_EXAMPLE_ENABLE_ADC_FEATURE +const int adc_channels[] = {CONFIG_EXAMPLE_ADC_PIN_CLK, + CONFIG_EXAMPLE_ADC_PIN_MOSI, + CONFIG_EXAMPLE_ADC_PIN_MISO, + CONFIG_EXAMPLE_ADC_PIN_CS}; +#endif //CONFIG_EXAMPLE_ENABLE_ADC_FEATURE + +pin_configuration_t config = { + .names = names, + .pins = pins, +#if CONFIG_EXAMPLE_ENABLE_ADC_FEATURE + .adc_channels = adc_channels, +#endif +}; +#endif //CONFIG_EXAMPLE_DEBUG_PIN_CONNECTIONS + // Pin assignments can be set in menuconfig, see "SD SPI Example Configuration" menu. // You can also change the pin assignments here by changing the following 4 lines. #define PIN_NUM_MISO CONFIG_EXAMPLE_PIN_MISO @@ -125,6 +150,9 @@ void app_main(void) } else { ESP_LOGE(TAG, "Failed to initialize the card (%s). " "Make sure SD card lines have pull-up resistors in place.", esp_err_to_name(ret)); +#ifdef CONFIG_EXAMPLE_DEBUG_PIN_CONNECTIONS + check_sd_card_pins(&config, pin_count); +#endif } return; }