• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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