1 /* 2 * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #pragma once 8 9 #include <stdint.h> 10 #include <stddef.h> 11 #include "esp_err.h" 12 #include "driver/sdmmc_types.h" 13 #include "driver/gpio.h" 14 #include "driver/spi_master.h" 15 16 #ifdef __cplusplus 17 extern "C" { 18 #endif 19 20 /// Handle representing an SD SPI device 21 typedef int sdspi_dev_handle_t; 22 23 #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 24 #define SDSPI_DEFAULT_HOST HSPI_HOST 25 #define SDSPI_DEFAULT_DMA SDSPI_DEFAULT_HOST 26 #else 27 #define SDSPI_DEFAULT_HOST SPI2_HOST 28 #define SDSPI_DEFAULT_DMA SPI_DMA_CH_AUTO 29 #endif 30 31 /** 32 * @brief Default sdmmc_host_t structure initializer for SD over SPI driver 33 * 34 * Uses SPI mode and max frequency set to 20MHz 35 * 36 * 'slot' should be set to an sdspi device initialized by `sdspi_host_init_device()`. 37 */ 38 #define SDSPI_HOST_DEFAULT() {\ 39 .flags = SDMMC_HOST_FLAG_SPI | SDMMC_HOST_FLAG_DEINIT_ARG, \ 40 .slot = SDSPI_DEFAULT_HOST, \ 41 .max_freq_khz = SDMMC_FREQ_DEFAULT, \ 42 .io_voltage = 3.3f, \ 43 .init = &sdspi_host_init, \ 44 .set_bus_width = NULL, \ 45 .get_bus_width = NULL, \ 46 .set_bus_ddr_mode = NULL, \ 47 .set_card_clk = &sdspi_host_set_card_clk, \ 48 .set_cclk_always_on = NULL, \ 49 .do_transaction = &sdspi_host_do_transaction, \ 50 .deinit_p = &sdspi_host_remove_device, \ 51 .io_int_enable = &sdspi_host_io_int_enable, \ 52 .io_int_wait = &sdspi_host_io_int_wait, \ 53 .command_timeout_ms = 0, \ 54 .get_real_freq = &sdspi_host_get_real_freq \ 55 } 56 57 /** 58 * Extra configuration for SD SPI device. 59 */ 60 typedef struct { 61 spi_host_device_t host_id; ///< SPI host to use, SPIx_HOST (see spi_types.h). 62 gpio_num_t gpio_cs; ///< GPIO number of CS signal 63 gpio_num_t gpio_cd; ///< GPIO number of card detect signal 64 gpio_num_t gpio_wp; ///< GPIO number of write protect signal 65 gpio_num_t gpio_int; ///< GPIO number of interrupt line (input) for SDIO card. 66 } sdspi_device_config_t; 67 68 #define SDSPI_SLOT_NO_CS GPIO_NUM_NC ///< indicates that card select line is not used 69 #define SDSPI_SLOT_NO_CD GPIO_NUM_NC ///< indicates that card detect line is not used 70 #define SDSPI_SLOT_NO_WP GPIO_NUM_NC ///< indicates that write protect line is not used 71 #define SDSPI_SLOT_NO_INT GPIO_NUM_NC ///< indicates that interrupt line is not used 72 73 /** 74 * Macro defining default configuration of SD SPI device. 75 */ 76 #define SDSPI_DEVICE_CONFIG_DEFAULT() {\ 77 .host_id = SDSPI_DEFAULT_HOST, \ 78 .gpio_cs = GPIO_NUM_13, \ 79 .gpio_cd = SDSPI_SLOT_NO_CD, \ 80 .gpio_wp = SDSPI_SLOT_NO_WP, \ 81 .gpio_int = GPIO_NUM_NC, \ 82 } 83 84 /** 85 * @brief Initialize SD SPI driver 86 * 87 * @note This function is not thread safe 88 * 89 * @return 90 * - ESP_OK on success 91 * - other error codes may be returned in future versions 92 */ 93 esp_err_t sdspi_host_init(void); 94 95 /** 96 * @brief Attach and initialize an SD SPI device on the specific SPI bus 97 * 98 * @note This function is not thread safe 99 * 100 * @note Initialize the SPI bus by `spi_bus_initialize()` before calling this function. 101 * 102 * @note The SDIO over sdspi needs an extra interrupt line. Call ``gpio_install_isr_service()`` before this function. 103 * 104 * @param dev_config pointer to device configuration structure 105 * @param out_handle Output of the handle to the sdspi device. 106 107 * @return 108 * - ESP_OK on success 109 * - ESP_ERR_INVALID_ARG if sdspi_host_init_device has invalid arguments 110 * - ESP_ERR_NO_MEM if memory can not be allocated 111 * - other errors from the underlying spi_master and gpio drivers 112 */ 113 esp_err_t sdspi_host_init_device(const sdspi_device_config_t* dev_config, sdspi_dev_handle_t* out_handle); 114 115 /** 116 * @brief Remove an SD SPI device 117 * 118 * @param handle Handle of the SD SPI device 119 * @return Always ESP_OK 120 */ 121 esp_err_t sdspi_host_remove_device(sdspi_dev_handle_t handle); 122 123 /** 124 * @brief Send command to the card and get response 125 * 126 * This function returns when command is sent and response is received, 127 * or data is transferred, or timeout occurs. 128 * 129 * @note This function is not thread safe w.r.t. init/deinit functions, 130 * and bus width/clock speed configuration functions. Multiple tasks 131 * can call sdspi_host_do_transaction as long as other sdspi_host_* 132 * functions are not called. 133 * 134 * @param handle Handle of the sdspi device 135 * @param cmdinfo pointer to structure describing command and data to transfer 136 * @return 137 * - ESP_OK on success 138 * - ESP_ERR_TIMEOUT if response or data transfer has timed out 139 * - ESP_ERR_INVALID_CRC if response or data transfer CRC check has failed 140 * - ESP_ERR_INVALID_RESPONSE if the card has sent an invalid response 141 */ 142 esp_err_t sdspi_host_do_transaction(sdspi_dev_handle_t handle, sdmmc_command_t *cmdinfo); 143 144 /** 145 * @brief Set card clock frequency 146 * 147 * Currently only integer fractions of 40MHz clock can be used. 148 * For High Speed cards, 40MHz can be used. 149 * For Default Speed cards, 20MHz can be used. 150 * 151 * @note This function is not thread safe 152 * 153 * @param host Handle of the sdspi device 154 * @param freq_khz card clock frequency, in kHz 155 * @return 156 * - ESP_OK on success 157 * - other error codes may be returned in the future 158 */ 159 esp_err_t sdspi_host_set_card_clk(sdspi_dev_handle_t host, uint32_t freq_khz); 160 161 /** 162 * @brief Calculate working frequency for specific device 163 * 164 * @param handle SDSPI device handle 165 * @param[out] real_freq_khz output parameter to hold the calculated frequency (in kHz) 166 * 167 * @return 168 * - ESP_ERR_INVALID_ARG : ``handle`` is NULL or invalid or ``real_freq_khz`` parameter is NULL 169 * - ESP_OK : Success 170 */ 171 esp_err_t sdspi_host_get_real_freq(sdspi_dev_handle_t handle, int* real_freq_khz); 172 173 /** 174 * @brief Release resources allocated using sdspi_host_init 175 * 176 * @note This function is not thread safe 177 * 178 * @return 179 * - ESP_OK on success 180 * - ESP_ERR_INVALID_STATE if sdspi_host_init function has not been called 181 */ 182 esp_err_t sdspi_host_deinit(void); 183 184 /** 185 * @brief Enable SDIO interrupt. 186 * 187 * @param handle Handle of the sdspi device 188 * 189 * @return 190 * - ESP_OK on success 191 */ 192 esp_err_t sdspi_host_io_int_enable(sdspi_dev_handle_t handle); 193 194 /** 195 * @brief Wait for SDIO interrupt until timeout. 196 * 197 * @param handle Handle of the sdspi device 198 * @param timeout_ticks Ticks to wait before timeout. 199 * 200 * @return 201 * - ESP_OK on success 202 */ 203 esp_err_t sdspi_host_io_int_wait(sdspi_dev_handle_t handle, TickType_t timeout_ticks); 204 205 #ifdef __cplusplus 206 } 207 #endif 208