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 "soc/soc_caps.h" 10 #if SOC_SDMMC_HOST_SUPPORTED 11 12 #include <stdint.h> 13 #include <stddef.h> 14 #include "esp_err.h" 15 #include "sdmmc_types.h" 16 #include "driver/gpio.h" 17 18 #ifdef __cplusplus 19 extern "C" { 20 #endif 21 22 #define SDMMC_HOST_SLOT_0 0 ///< SDMMC slot 0 23 #define SDMMC_HOST_SLOT_1 1 ///< SDMMC slot 1 24 25 /** 26 * @brief Default sdmmc_host_t structure initializer for SDMMC peripheral 27 * 28 * Uses SDMMC peripheral, with 4-bit mode enabled, and max frequency set to 20MHz 29 */ 30 #define SDMMC_HOST_DEFAULT() {\ 31 .flags = SDMMC_HOST_FLAG_8BIT | \ 32 SDMMC_HOST_FLAG_4BIT | \ 33 SDMMC_HOST_FLAG_1BIT | \ 34 SDMMC_HOST_FLAG_DDR, \ 35 .slot = SDMMC_HOST_SLOT_1, \ 36 .max_freq_khz = SDMMC_FREQ_DEFAULT, \ 37 .io_voltage = 3.3f, \ 38 .init = &sdmmc_host_init, \ 39 .set_bus_width = &sdmmc_host_set_bus_width, \ 40 .get_bus_width = &sdmmc_host_get_slot_width, \ 41 .set_bus_ddr_mode = &sdmmc_host_set_bus_ddr_mode, \ 42 .set_card_clk = &sdmmc_host_set_card_clk, \ 43 .do_transaction = &sdmmc_host_do_transaction, \ 44 .deinit = &sdmmc_host_deinit, \ 45 .io_int_enable = sdmmc_host_io_int_enable, \ 46 .io_int_wait = sdmmc_host_io_int_wait, \ 47 .command_timeout_ms = 0, \ 48 } 49 50 /** 51 * Extra configuration for SDMMC peripheral slot 52 */ 53 typedef struct { 54 #ifdef SOC_SDMMC_USE_GPIO_MATRIX 55 gpio_num_t clk; ///< GPIO number of CLK signal. 56 gpio_num_t cmd; ///< GPIO number of CMD signal. 57 gpio_num_t d0; ///< GPIO number of D0 signal. 58 gpio_num_t d1; ///< GPIO number of D1 signal. 59 gpio_num_t d2; ///< GPIO number of D2 signal. 60 gpio_num_t d3; ///< GPIO number of D3 signal. 61 gpio_num_t d4; ///< GPIO number of D4 signal. Ignored in 1- or 4- line mode. 62 gpio_num_t d5; ///< GPIO number of D5 signal. Ignored in 1- or 4- line mode. 63 gpio_num_t d6; ///< GPIO number of D6 signal. Ignored in 1- or 4- line mode. 64 gpio_num_t d7; ///< GPIO number of D7 signal. Ignored in 1- or 4- line mode. 65 #endif // SOC_SDMMC_USE_GPIO_MATRIX 66 union { 67 gpio_num_t gpio_cd; ///< GPIO number of card detect signal 68 gpio_num_t cd; ///< GPIO number of card detect signal; shorter name. 69 }; 70 union { 71 gpio_num_t gpio_wp; ///< GPIO number of write protect signal 72 gpio_num_t wp; ///< GPIO number of write protect signal; shorter name. 73 }; 74 uint8_t width; ///< Bus width used by the slot (might be less than the max width supported) 75 uint32_t flags; ///< Features used by this slot 76 #define SDMMC_SLOT_FLAG_INTERNAL_PULLUP BIT(0) 77 /**< Enable internal pullups on enabled pins. The internal pullups 78 are insufficient however, please make sure external pullups are 79 connected on the bus. This is for debug / example purpose only. 80 */ 81 } sdmmc_slot_config_t; 82 83 #define SDMMC_SLOT_NO_CD GPIO_NUM_NC ///< indicates that card detect line is not used 84 #define SDMMC_SLOT_NO_WP GPIO_NUM_NC ///< indicates that write protect line is not used 85 #define SDMMC_SLOT_WIDTH_DEFAULT 0 ///< use the maximum possible width for the slot 86 87 #ifdef SOC_SDMMC_USE_GPIO_MATRIX 88 89 /** 90 * Macro defining default configuration of SDMMC host slot 91 */ 92 #define SDMMC_SLOT_CONFIG_DEFAULT() {\ 93 .clk = GPIO_NUM_14, \ 94 .cmd = GPIO_NUM_15, \ 95 .d0 = GPIO_NUM_2, \ 96 .d1 = GPIO_NUM_4, \ 97 .d2 = GPIO_NUM_12, \ 98 .d3 = GPIO_NUM_13, \ 99 .d4 = GPIO_NUM_33, \ 100 .d5 = GPIO_NUM_34, \ 101 .d6 = GPIO_NUM_35, \ 102 .d7 = GPIO_NUM_36, \ 103 .cd = SDMMC_SLOT_NO_CD, \ 104 .wp = SDMMC_SLOT_NO_WP, \ 105 .width = SDMMC_SLOT_WIDTH_DEFAULT, \ 106 .flags = 0, \ 107 } 108 109 #else // SOC_SDMMC_USE_GPIO_MATRIX 110 111 /** 112 * Macro defining default configuration of SDMMC host slot 113 */ 114 #define SDMMC_SLOT_CONFIG_DEFAULT() {\ 115 .cd = SDMMC_SLOT_NO_CD, \ 116 .wp = SDMMC_SLOT_NO_WP, \ 117 .width = SDMMC_SLOT_WIDTH_DEFAULT, \ 118 .flags = 0, \ 119 } 120 121 #endif // SOC_SDMMC_USE_GPIO_MATRIX 122 123 /** 124 * @brief Initialize SDMMC host peripheral 125 * 126 * @note This function is not thread safe 127 * 128 * @return 129 * - ESP_OK on success 130 * - ESP_ERR_INVALID_STATE if sdmmc_host_init was already called 131 * - ESP_ERR_NO_MEM if memory can not be allocated 132 */ 133 esp_err_t sdmmc_host_init(void); 134 135 /** 136 * @brief Initialize given slot of SDMMC peripheral 137 * 138 * On the ESP32, SDMMC peripheral has two slots: 139 * - Slot 0: 8-bit wide, maps to HS1_* signals in PIN MUX 140 * - Slot 1: 4-bit wide, maps to HS2_* signals in PIN MUX 141 * 142 * Card detect and write protect signals can be routed to 143 * arbitrary GPIOs using GPIO matrix. 144 * 145 * @note This function is not thread safe 146 * 147 * @param slot slot number (SDMMC_HOST_SLOT_0 or SDMMC_HOST_SLOT_1) 148 * @param slot_config additional configuration for the slot 149 * @return 150 * - ESP_OK on success 151 * - ESP_ERR_INVALID_STATE if host has not been initialized using sdmmc_host_init 152 */ 153 esp_err_t sdmmc_host_init_slot(int slot, const sdmmc_slot_config_t* slot_config); 154 155 /** 156 * @brief Select bus width to be used for data transfer 157 * 158 * SD/MMC card must be initialized prior to this command, and a command to set 159 * bus width has to be sent to the card (e.g. SD_APP_SET_BUS_WIDTH) 160 * 161 * @note This function is not thread safe 162 * 163 * @param slot slot number (SDMMC_HOST_SLOT_0 or SDMMC_HOST_SLOT_1) 164 * @param width bus width (1, 4, or 8 for slot 0; 1 or 4 for slot 1) 165 * @return 166 * - ESP_OK on success 167 * - ESP_ERR_INVALID_ARG if slot number or width is not valid 168 */ 169 esp_err_t sdmmc_host_set_bus_width(int slot, size_t width); 170 171 /** 172 * @brief Get bus width configured in ``sdmmc_host_init_slot`` to be used for data transfer 173 * 174 * @param slot slot number (SDMMC_HOST_SLOT_0 or SDMMC_HOST_SLOT_1) 175 * @return configured bus width of the specified slot. 176 */ 177 size_t sdmmc_host_get_slot_width(int slot); 178 179 /** 180 * @brief Set card clock frequency 181 * 182 * Currently only integer fractions of 40MHz clock can be used. 183 * For High Speed cards, 40MHz can be used. 184 * For Default Speed cards, 20MHz can be used. 185 * 186 * @note This function is not thread safe 187 * 188 * @param slot slot number (SDMMC_HOST_SLOT_0 or SDMMC_HOST_SLOT_1) 189 * @param freq_khz card clock frequency, in kHz 190 * @return 191 * - ESP_OK on success 192 * - other error codes may be returned in the future 193 */ 194 esp_err_t sdmmc_host_set_card_clk(int slot, uint32_t freq_khz); 195 196 /** 197 * @brief Enable or disable DDR mode of SD interface 198 * @param slot slot number (SDMMC_HOST_SLOT_0 or SDMMC_HOST_SLOT_1) 199 * @param ddr_enabled enable or disable DDR mode 200 * @return 201 * - ESP_OK on success 202 * - ESP_ERR_NOT_SUPPORTED if DDR mode is not supported on this slot 203 */ 204 esp_err_t sdmmc_host_set_bus_ddr_mode(int slot, bool ddr_enabled); 205 206 /** 207 * @brief Send command to the card and get response 208 * 209 * This function returns when command is sent and response is received, 210 * or data is transferred, or timeout occurs. 211 * 212 * @note This function is not thread safe w.r.t. init/deinit functions, 213 * and bus width/clock speed configuration functions. Multiple tasks 214 * can call sdmmc_host_do_transaction as long as other sdmmc_host_* 215 * functions are not called. 216 * 217 * @attention Data buffer passed in cmdinfo->data must be in DMA capable memory 218 * 219 * @param slot slot number (SDMMC_HOST_SLOT_0 or SDMMC_HOST_SLOT_1) 220 * @param cmdinfo pointer to structure describing command and data to transfer 221 * @return 222 * - ESP_OK on success 223 * - ESP_ERR_TIMEOUT if response or data transfer has timed out 224 * - ESP_ERR_INVALID_CRC if response or data transfer CRC check has failed 225 * - ESP_ERR_INVALID_RESPONSE if the card has sent an invalid response 226 * - ESP_ERR_INVALID_SIZE if the size of data transfer is not valid in SD protocol 227 * - ESP_ERR_INVALID_ARG if the data buffer is not in DMA capable memory 228 */ 229 esp_err_t sdmmc_host_do_transaction(int slot, sdmmc_command_t* cmdinfo); 230 231 /** 232 * @brief Enable IO interrupts 233 * 234 * This function configures the host to accept SDIO interrupts. 235 * 236 * @param slot slot number (SDMMC_HOST_SLOT_0 or SDMMC_HOST_SLOT_1) 237 * @return returns ESP_OK, other errors possible in the future 238 */ 239 esp_err_t sdmmc_host_io_int_enable(int slot); 240 241 /** 242 * @brief Block until an SDIO interrupt is received, or timeout occurs 243 * @param slot slot number (SDMMC_HOST_SLOT_0 or SDMMC_HOST_SLOT_1) 244 * @param timeout_ticks number of RTOS ticks to wait for the interrupt 245 * @return 246 * - ESP_OK on success (interrupt received) 247 * - ESP_ERR_TIMEOUT if the interrupt did not occur within timeout_ticks 248 */ 249 esp_err_t sdmmc_host_io_int_wait(int slot, TickType_t timeout_ticks); 250 251 /** 252 * @brief Disable SDMMC host and release allocated resources 253 * 254 * @note This function is not thread safe 255 * 256 * @return 257 * - ESP_OK on success 258 * - ESP_ERR_INVALID_STATE if sdmmc_host_init function has not been called 259 */ 260 esp_err_t sdmmc_host_deinit(void); 261 262 /** 263 * @brief Enable the pull-ups of sd pins. 264 * 265 * This function is deprecated. Please set SDMMC_SLOT_FLAG_INTERNAL_PULLUP flag in 266 * sdmmc_slot_config_t::flags instead. 267 * 268 * @note You should always place actual pullups on the lines instead of using 269 * this function. Internal pullup resistance are high and not sufficient, may 270 * cause instability in products. This is for debug or examples only. 271 * 272 * @param slot Slot to use, normally set it to 1. 273 * @param width Bit width of your configuration, 1 or 4. 274 * 275 * @return 276 * - ESP_OK: if success 277 * - ESP_ERR_INVALID_ARG: if configured width larger than maximum the slot can 278 * support 279 */ 280 esp_err_t sdmmc_host_pullup_en(int slot, int width) __attribute__((deprecated)); 281 282 #ifdef __cplusplus 283 } 284 #endif 285 286 #endif //SOC_SDMMC_HOST_SUPPORTED 287