1 // Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #pragma once 16 17 #include <stdint.h> 18 #include <stddef.h> 19 #include "esp_err.h" 20 #include "sdmmc_types.h" 21 #include "driver/gpio.h" 22 #include "driver/spi_master.h" 23 24 #ifdef __cplusplus 25 extern "C" { 26 #endif 27 28 /// Handle representing an SD SPI device 29 typedef int sdspi_dev_handle_t; 30 31 #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 32 #define SDSPI_DEFAULT_HOST HSPI_HOST 33 #else 34 #define SDSPI_DEFAULT_HOST SPI2_HOST 35 #endif 36 37 /** 38 * @brief Default sdmmc_host_t structure initializer for SD over SPI driver 39 * 40 * Uses SPI mode and max frequency set to 20MHz 41 * 42 * 'slot' should be set to an sdspi device initialized by `sdspi_host_init_device()`. 43 */ 44 #define SDSPI_HOST_DEFAULT() {\ 45 .flags = SDMMC_HOST_FLAG_SPI | SDMMC_HOST_FLAG_DEINIT_ARG, \ 46 .slot = SDSPI_DEFAULT_HOST, \ 47 .max_freq_khz = SDMMC_FREQ_DEFAULT, \ 48 .io_voltage = 3.3f, \ 49 .init = &sdspi_host_init, \ 50 .set_bus_width = NULL, \ 51 .get_bus_width = NULL, \ 52 .set_bus_ddr_mode = NULL, \ 53 .set_card_clk = &sdspi_host_set_card_clk, \ 54 .do_transaction = &sdspi_host_do_transaction, \ 55 .deinit_p = &sdspi_host_remove_device, \ 56 .io_int_enable = &sdspi_host_io_int_enable, \ 57 .io_int_wait = &sdspi_host_io_int_wait, \ 58 .command_timeout_ms = 0, \ 59 } 60 61 /** 62 * Extra configuration for SD SPI device. 63 */ 64 typedef struct { 65 spi_host_device_t host_id; ///< SPI host to use, SPIx_HOST (see spi_types.h). 66 gpio_num_t gpio_cs; ///< GPIO number of CS signal 67 gpio_num_t gpio_cd; ///< GPIO number of card detect signal 68 gpio_num_t gpio_wp; ///< GPIO number of write protect signal 69 gpio_num_t gpio_int; ///< GPIO number of interrupt line (input) for SDIO card. 70 } sdspi_device_config_t; 71 72 #define SDSPI_SLOT_NO_CD GPIO_NUM_NC ///< indicates that card detect line is not used 73 #define SDSPI_SLOT_NO_WP GPIO_NUM_NC ///< indicates that write protect line is not used 74 #define SDSPI_SLOT_NO_INT GPIO_NUM_NC ///< indicates that interrupt line is not used 75 76 /** 77 * Macro defining default configuration of SD SPI device. 78 */ 79 #define SDSPI_DEVICE_CONFIG_DEFAULT() {\ 80 .host_id = SDSPI_DEFAULT_HOST, \ 81 .gpio_cs = GPIO_NUM_13, \ 82 .gpio_cd = SDSPI_SLOT_NO_CD, \ 83 .gpio_wp = SDSPI_SLOT_NO_WP, \ 84 .gpio_int = GPIO_NUM_NC, \ 85 } 86 87 /** 88 * @brief Initialize SD SPI driver 89 * 90 * @note This function is not thread safe 91 * 92 * @return 93 * - ESP_OK on success 94 * - other error codes may be returned in future versions 95 */ 96 esp_err_t sdspi_host_init(void); 97 98 /** 99 * @brief Attach and initialize an SD SPI device on the specific SPI bus 100 * 101 * @note This function is not thread safe 102 * 103 * @note Initialize the SPI bus by `spi_bus_initialize()` before calling this function. 104 * 105 * @note The SDIO over sdspi needs an extra interrupt line. Call ``gpio_install_isr_service()`` before this function. 106 * 107 * @param dev_config pointer to device configuration structure 108 * @param out_handle Output of the handle to the sdspi device. 109 110 * @return 111 * - ESP_OK on success 112 * - ESP_ERR_INVALID_ARG if sdspi_host_init_device has invalid arguments 113 * - ESP_ERR_NO_MEM if memory can not be allocated 114 * - other errors from the underlying spi_master and gpio drivers 115 */ 116 esp_err_t sdspi_host_init_device(const sdspi_device_config_t* dev_config, sdspi_dev_handle_t* out_handle); 117 118 /** 119 * @brief Remove an SD SPI device 120 * 121 * @param handle Handle of the SD SPI device 122 * @return Always ESP_OK 123 */ 124 esp_err_t sdspi_host_remove_device(sdspi_dev_handle_t handle); 125 126 /** 127 * @brief Send command to the card and get response 128 * 129 * This function returns when command is sent and response is received, 130 * or data is transferred, or timeout occurs. 131 * 132 * @note This function is not thread safe w.r.t. init/deinit functions, 133 * and bus width/clock speed configuration functions. Multiple tasks 134 * can call sdspi_host_do_transaction as long as other sdspi_host_* 135 * functions are not called. 136 * 137 * @param handle Handle of the sdspi device 138 * @param cmdinfo pointer to structure describing command and data to transfer 139 * @return 140 * - ESP_OK on success 141 * - ESP_ERR_TIMEOUT if response or data transfer has timed out 142 * - ESP_ERR_INVALID_CRC if response or data transfer CRC check has failed 143 * - ESP_ERR_INVALID_RESPONSE if the card has sent an invalid response 144 */ 145 esp_err_t sdspi_host_do_transaction(sdspi_dev_handle_t handle, sdmmc_command_t *cmdinfo); 146 147 /** 148 * @brief Set card clock frequency 149 * 150 * Currently only integer fractions of 40MHz clock can be used. 151 * For High Speed cards, 40MHz can be used. 152 * For Default Speed cards, 20MHz can be used. 153 * 154 * @note This function is not thread safe 155 * 156 * @param host Handle of the sdspi device 157 * @param freq_khz card clock frequency, in kHz 158 * @return 159 * - ESP_OK on success 160 * - other error codes may be returned in the future 161 */ 162 esp_err_t sdspi_host_set_card_clk(sdspi_dev_handle_t host, uint32_t freq_khz); 163 164 /** 165 * @brief Release resources allocated using sdspi_host_init 166 * 167 * @note This function is not thread safe 168 * 169 * @return 170 * - ESP_OK on success 171 * - ESP_ERR_INVALID_STATE if sdspi_host_init function has not been called 172 */ 173 esp_err_t sdspi_host_deinit(void); 174 175 /** 176 * @brief Enable SDIO interrupt. 177 * 178 * @param handle Handle of the sdspi device 179 * 180 * @return 181 * - ESP_OK on success 182 */ 183 esp_err_t sdspi_host_io_int_enable(sdspi_dev_handle_t handle); 184 185 /** 186 * @brief Wait for SDIO interrupt until timeout. 187 * 188 * @param handle Handle of the sdspi device 189 * @param timeout_ticks Ticks to wait before timeout. 190 * 191 * @return 192 * - ESP_OK on success 193 */ 194 esp_err_t sdspi_host_io_int_wait(sdspi_dev_handle_t handle, TickType_t timeout_ticks); 195 196 /******************************************************************************* 197 * Deprecated APIs 198 ******************************************************************************/ 199 200 /** 201 * Extra configuration for SPI host. 202 * 203 * @deprecated Use `sdspi_device_config_t` and corresponding `sdspi_host_init_device()` instead. 204 */ 205 typedef struct { 206 gpio_num_t gpio_cs; ///< GPIO number of CS signal 207 gpio_num_t gpio_cd; ///< GPIO number of card detect signal 208 gpio_num_t gpio_wp; ///< GPIO number of write protect signal 209 gpio_num_t gpio_int; ///< GPIO number of interrupt line (input) for SDIO card. 210 gpio_num_t gpio_miso; ///< GPIO number of MISO signal. 211 gpio_num_t gpio_mosi; ///< GPIO number of MOSI signal. 212 gpio_num_t gpio_sck; ///< GPIO number of SCK signal. 213 int dma_channel; ///< DMA channel to be used by SPI driver (1 or 2). 214 } sdspi_slot_config_t; 215 216 /** 217 * Macro defining default configuration of SPI host 218 */ 219 #define SDSPI_SLOT_CONFIG_DEFAULT() {\ 220 .gpio_cs = GPIO_NUM_13, \ 221 .gpio_cd = SDSPI_SLOT_NO_CD, \ 222 .gpio_wp = SDSPI_SLOT_NO_WP, \ 223 .gpio_int = GPIO_NUM_NC, \ 224 .gpio_miso = GPIO_NUM_2, \ 225 .gpio_mosi = GPIO_NUM_15, \ 226 .gpio_sck = GPIO_NUM_14, \ 227 .dma_channel = 1, \ 228 } 229 230 /** 231 * @brief Initialize SD SPI driver for the specific SPI controller 232 * 233 * @note This function is not thread safe 234 * 235 * @note The SDIO over sdspi needs an extra interrupt line. Call ``gpio_install_isr_service()`` before this function. 236 * 237 * @param slot SPI controller to use (SPI2_HOST or SPI3_HOST) 238 * @param slot_config pointer to slot configuration structure 239 240 * @deprecated Use `sdspi_host_init_device` instead. 241 * 242 * @return 243 * - ESP_OK on success 244 * - ESP_ERR_INVALID_ARG if sdspi_init_slot has invalid arguments 245 * - ESP_ERR_NO_MEM if memory can not be allocated 246 * - other errors from the underlying spi_master and gpio drivers 247 */ 248 esp_err_t sdspi_host_init_slot(int slot, const sdspi_slot_config_t* slot_config); 249 250 #ifdef __cplusplus 251 } 252 #endif 253