#include "driver/sdmmc_host.h"
#include "driver/sdspi_host.h"
#include "driver/sdmmc_defs.h"
+#include "soc/gpio_reg.h"
#include "sdmmc_cmd.h"
#include "esp_log.h"
#include "esp_heap_caps.h"
#include <time.h>
#include <sys/time.h>
+#include <unistd.h>
TEST_CASE("MMC_RSP_BITS", "[sd]")
{
free(card);
TEST_ESP_OK(sdmmc_host_deinit());
}
+
+static void test_cd_input(int gpio_cd_num, const sdmmc_host_t* config)
+{
+ sdmmc_card_t* card = malloc(sizeof(sdmmc_card_t));
+ TEST_ASSERT_NOT_NULL(card);
+
+ // SDMMC host should have configured CD as input.
+ // Enable output as well (not using the driver, to avoid touching input
+ // enable bits).
+ gpio_matrix_out(gpio_cd_num, SIG_GPIO_OUT_IDX, false, false);
+ REG_WRITE(GPIO_ENABLE_W1TS_REG, BIT(gpio_cd_num));
+
+ // Check that card initialization fails if CD is high
+ REG_WRITE(GPIO_OUT_W1TS_REG, BIT(gpio_cd_num));
+ usleep(100);
+ TEST_ESP_ERR(ESP_ERR_NOT_FOUND, sdmmc_card_init(config, card));
+
+ // Check that card initialization succeeds if CD is low
+ REG_WRITE(GPIO_OUT_W1TC_REG, BIT(gpio_cd_num));
+ usleep(100);
+ TEST_ESP_OK(sdmmc_card_init(config, card));
+
+ free(card);
+}
+
+TEST_CASE("CD input works in SD mode", "[sd][test_env=UT_T1_SDMODE]")
+{
+ sdmmc_host_t config = SDMMC_HOST_DEFAULT();
+ sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
+ const int gpio_cd_num = 5;
+ slot_config.gpio_cd = gpio_cd_num;
+ TEST_ESP_OK(sdmmc_host_init());
+ TEST_ESP_OK(sdmmc_host_init_slot(SDMMC_HOST_SLOT_1, &slot_config));
+
+ test_cd_input(gpio_cd_num, &config);
+
+ TEST_ESP_OK(sdmmc_host_deinit());
+}
+
+TEST_CASE("CD input works in SPI mode", "[sd][test_env=UT_T1_SPIMODE]")
+{
+ sdmmc_host_t config = SDSPI_HOST_DEFAULT();
+ sdspi_slot_config_t slot_config = SDSPI_SLOT_CONFIG_DEFAULT();
+ const int gpio_cd_num = 5;
+ slot_config.gpio_cd = gpio_cd_num;
+ TEST_ESP_OK(sdspi_host_init());
+ TEST_ESP_OK(sdspi_host_init_slot(config.slot, &slot_config));
+
+ test_cd_input(gpio_cd_num, &config);
+
+ TEST_ESP_OK(sdspi_host_deinit());
+}
+
+static void test_wp_input(int gpio_wp_num, const sdmmc_host_t* config)
+{
+ sdmmc_card_t* card = malloc(sizeof(sdmmc_card_t));
+ TEST_ASSERT_NOT_NULL(card);
+
+ // SDMMC host should have configured WP as input.
+ // Enable output as well (not using the driver, to avoid touching input
+ // enable bits).
+ gpio_matrix_out(gpio_wp_num, SIG_GPIO_OUT_IDX, false, false);
+ REG_WRITE(GPIO_ENABLE_W1TS_REG, BIT(gpio_wp_num));
+
+ // Check that the card can be initialized with WP low
+ REG_WRITE(GPIO_OUT_W1TC_REG, BIT(gpio_wp_num));
+ TEST_ESP_OK(sdmmc_card_init(config, card));
+
+ uint32_t* data = heap_caps_calloc(1, 512, MALLOC_CAP_DMA);
+
+ // Check that card write succeeds if WP is high
+ REG_WRITE(GPIO_OUT_W1TS_REG, BIT(gpio_wp_num));
+ usleep(100);
+ TEST_ESP_OK(sdmmc_write_sectors(card, &data, 0, 1));
+
+ // Check that write fails if WP is low
+ REG_WRITE(GPIO_OUT_W1TC_REG, BIT(gpio_wp_num));
+ usleep(100);
+ TEST_ESP_ERR(ESP_ERR_INVALID_STATE, sdmmc_write_sectors(card, &data, 0, 1));
+ // ...but reads still work
+ TEST_ESP_OK(sdmmc_read_sectors(card, &data, 0, 1));
+
+ free(data);
+ free(card);
+}
+
+TEST_CASE("WP input works in SD mode", "[sd][test_env=UT_T1_SDMODE]")
+{
+ sdmmc_host_t config = SDMMC_HOST_DEFAULT();
+ sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
+ const int gpio_wp_num = 5;
+ slot_config.gpio_wp = gpio_wp_num;
+ TEST_ESP_OK(sdmmc_host_init());
+ TEST_ESP_OK(sdmmc_host_init_slot(SDMMC_HOST_SLOT_1, &slot_config));
+
+ test_wp_input(gpio_wp_num, &config);
+
+ TEST_ESP_OK(sdmmc_host_deinit());
+}
+
+TEST_CASE("WP input works in SPI mode", "[sd][test_env=UT_T1_SPIMODE]")
+{
+ sdmmc_host_t config = SDSPI_HOST_DEFAULT();
+ sdspi_slot_config_t slot_config = SDSPI_SLOT_CONFIG_DEFAULT();
+ const int gpio_wp_num = 5;
+ slot_config.gpio_wp = gpio_wp_num;
+ TEST_ESP_OK(sdspi_host_init());
+ TEST_ESP_OK(sdspi_host_init_slot(config.slot, &slot_config));
+
+ test_wp_input(gpio_wp_num, &config);
+
+ TEST_ESP_OK(sdspi_host_deinit());
+}