2021-05-24 01:50:04 +02:00
/*
2024-03-29 11:36:27 +08:00
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
2021-05-24 01:50:04 +02:00
*
* SPDX-License-Identifier: Apache-2.0
*/
2017-07-04 13:58:36 +08:00
# pragma once
# include <stdint.h>
# include <stddef.h>
# include "esp_err.h"
2023-11-16 15:17:04 +08:00
# include "sd_protocol_types.h"
2017-07-04 13:58:36 +08:00
# include "driver/gpio.h"
# include "driver/spi_master.h"
# ifdef __cplusplus
extern " C " {
# endif
2018-09-03 23:55:22 +08:00
/// Handle representing an SD SPI device
typedef int sdspi_dev_handle_t ;
2024-12-03 11:25:43 +08:00
# if CONFIG_IDF_TARGET_ESP32
# define SDSPI_DEFAULT_HOST SPI2_HOST
# define SDSPI_DEFAULT_DMA SDSPI_DEFAULT_HOST
# elif CONFIG_IDF_TARGET_ESP32S2
# define SDSPI_DEFAULT_HOST SPI3_HOST
2022-02-08 18:38:06 +01:00
# define SDSPI_DEFAULT_DMA SDSPI_DEFAULT_HOST
2021-03-05 16:20:33 +08:00
# else
# define SDSPI_DEFAULT_HOST SPI2_HOST
2022-02-08 18:38:06 +01:00
# define SDSPI_DEFAULT_DMA SPI_DMA_CH_AUTO
2021-03-05 16:20:33 +08:00
# endif
2017-07-04 13:58:36 +08:00
/**
* @brief Default sdmmc_host_t structure initializer for SD over SPI driver
*
* Uses SPI mode and max frequency set to 20MHz
*
2018-09-03 23:55:22 +08:00
* 'slot' should be set to an sdspi device initialized by `sdspi_host_init_device()`.
2017-07-04 13:58:36 +08:00
*/
# define SDSPI_HOST_DEFAULT() {\
2018-09-03 23:55:22 +08:00
.flags = SDMMC_HOST_FLAG_SPI | SDMMC_HOST_FLAG_DEINIT_ARG, \
2021-03-05 16:20:33 +08:00
.slot = SDSPI_DEFAULT_HOST, \
2017-07-04 13:58:36 +08:00
.max_freq_khz = SDMMC_FREQ_DEFAULT, \
.io_voltage = 3.3f, \
2024-11-06 12:09:25 +08:00
.driver_strength = SDMMC_DRIVER_STRENGTH_B, \
.current_limit = SDMMC_CURRENT_LIMIT_200MA, \
2017-07-04 13:58:36 +08:00
.init = &sdspi_host_init, \
.set_bus_width = NULL, \
2018-04-23 14:35:13 +08:00
.get_bus_width = NULL, \
2018-08-22 18:16:32 +08:00
.set_bus_ddr_mode = NULL, \
2017-07-04 13:58:36 +08:00
.set_card_clk = &sdspi_host_set_card_clk, \
2022-09-19 21:15:23 +02:00
.set_cclk_always_on = NULL, \
2017-07-04 13:58:36 +08:00
.do_transaction = &sdspi_host_do_transaction, \
2018-09-03 23:55:22 +08:00
.deinit_p = &sdspi_host_remove_device, \
2018-12-29 02:04:37 +08:00
.io_int_enable = &sdspi_host_io_int_enable, \
.io_int_wait = &sdspi_host_io_int_wait, \
2017-11-08 12:52:25 +08:00
.command_timeout_ms = 0, \
2023-04-18 19:50:01 +08:00
.get_real_freq = &sdspi_host_get_real_freq, \
.input_delay_phase = SDMMC_DELAY_PHASE_0, \
2024-03-29 11:36:27 +08:00
.set_input_delay = NULL, \
2024-08-01 14:15:41 +09:00
.dma_aligned_buffer = NULL, \
.pwr_ctrl_handle = NULL, \
2024-03-29 11:36:27 +08:00
.get_dma_info = &sdspi_host_get_dma_info, \
2024-11-06 12:09:25 +08:00
.is_slot_set_to_uhs1 = NULL, \
2017-07-04 13:58:36 +08:00
}
/**
2018-09-03 23:55:22 +08:00
* Extra configuration for SD SPI device.
2017-07-04 13:58:36 +08:00
*/
typedef struct {
2018-09-03 23:55:22 +08:00
spi_host_device_t host_id ; ///< SPI host to use, SPIx_HOST (see spi_types.h).
2023-06-15 09:22:07 +02:00
gpio_num_t gpio_cs ; ///< GPIO number of CS signal
gpio_num_t gpio_cd ; ///< GPIO number of card detect signal
gpio_num_t gpio_wp ; ///< GPIO number of write protect signal
gpio_num_t gpio_int ; ///< GPIO number of interrupt line (input) for SDIO card.
2023-10-19 14:38:32 +08:00
bool gpio_wp_polarity ; /*!< GPIO write protect polarity
0 means "active low", i.e. card is protected when the GPIO is low;
1 means "active high", i.e. card is protected when GPIO is high. */
2024-08-08 14:42:00 +08:00
uint16_t duty_cycle_pos ; ///< Duty cycle of positive clock, in 1/256th increments (128 = 50%/50% duty). Setting this to 0 (=not setting it) is equivalent to setting this to 128.
2018-09-03 23:55:22 +08:00
} sdspi_device_config_t ;
2017-07-04 13:58:36 +08:00
2023-06-15 09:22:07 +02:00
# define SDSPI_SLOT_NO_CS GPIO_NUM_NC ///< indicates that card select line is not used
# define SDSPI_SLOT_NO_CD GPIO_NUM_NC ///< indicates that card detect line is not used
# define SDSPI_SLOT_NO_WP GPIO_NUM_NC ///< indicates that write protect line is not used
# define SDSPI_SLOT_NO_INT GPIO_NUM_NC ///< indicates that interrupt line is not used
# define SDSPI_IO_ACTIVE_LOW 0
2017-07-04 13:58:36 +08:00
/**
2018-09-03 23:55:22 +08:00
* Macro defining default configuration of SD SPI device.
2017-07-04 13:58:36 +08:00
*/
2018-09-03 23:55:22 +08:00
# define SDSPI_DEVICE_CONFIG_DEFAULT() {\
2021-03-05 16:20:33 +08:00
.host_id = SDSPI_DEFAULT_HOST, \
2017-07-04 13:58:36 +08:00
.gpio_cs = GPIO_NUM_13, \
2018-04-23 14:35:13 +08:00
.gpio_cd = SDSPI_SLOT_NO_CD, \
.gpio_wp = SDSPI_SLOT_NO_WP, \
2018-12-29 02:04:37 +08:00
.gpio_int = GPIO_NUM_NC, \
2023-06-15 09:22:07 +02:00
.gpio_wp_polarity = SDSPI_IO_ACTIVE_LOW, \
2024-08-08 14:42:00 +08:00
.duty_cycle_pos = 0,\
2017-07-04 13:58:36 +08:00
}
/**
* @brief Initialize SD SPI driver
*
* @note This function is not thread safe
*
* @return
* - ESP_OK on success
* - other error codes may be returned in future versions
*/
2019-07-16 16:33:30 +07:00
esp_err_t sdspi_host_init ( void ) ;
2017-07-04 13:58:36 +08:00
/**
2018-09-03 23:55:22 +08:00
* @brief Attach and initialize an SD SPI device on the specific SPI bus
2017-07-04 13:58:36 +08:00
*
* @note This function is not thread safe
*
2018-09-03 23:55:22 +08:00
* @note Initialize the SPI bus by `spi_bus_initialize()` before calling this function.
2018-12-29 02:04:37 +08:00
*
2018-09-03 23:55:22 +08:00
* @note The SDIO over sdspi needs an extra interrupt line. Call ``gpio_install_isr_service()`` before this function.
2017-07-04 13:58:36 +08:00
*
2018-09-03 23:55:22 +08:00
* @param dev_config pointer to device configuration structure
* @param out_handle Output of the handle to the sdspi device.
2017-07-04 13:58:36 +08:00
* @return
* - ESP_OK on success
2018-09-03 23:55:22 +08:00
* - ESP_ERR_INVALID_ARG if sdspi_host_init_device has invalid arguments
2017-07-04 13:58:36 +08:00
* - ESP_ERR_NO_MEM if memory can not be allocated
* - other errors from the underlying spi_master and gpio drivers
*/
2018-09-03 23:55:22 +08:00
esp_err_t sdspi_host_init_device ( const sdspi_device_config_t * dev_config , sdspi_dev_handle_t * out_handle ) ;
/**
* @brief Remove an SD SPI device
*
* @param handle Handle of the SD SPI device
* @return Always ESP_OK
*/
esp_err_t sdspi_host_remove_device ( sdspi_dev_handle_t handle ) ;
2017-07-04 13:58:36 +08:00
/**
* @brief Send command to the card and get response
*
* This function returns when command is sent and response is received,
* or data is transferred, or timeout occurs.
*
* @note This function is not thread safe w.r.t. init/deinit functions,
* and bus width/clock speed configuration functions. Multiple tasks
* can call sdspi_host_do_transaction as long as other sdspi_host_*
* functions are not called.
*
2018-09-03 23:55:22 +08:00
* @param handle Handle of the sdspi device
2017-07-04 13:58:36 +08:00
* @param cmdinfo pointer to structure describing command and data to transfer
* @return
* - ESP_OK on success
* - ESP_ERR_TIMEOUT if response or data transfer has timed out
* - ESP_ERR_INVALID_CRC if response or data transfer CRC check has failed
* - ESP_ERR_INVALID_RESPONSE if the card has sent an invalid response
*/
2018-09-03 23:55:22 +08:00
esp_err_t sdspi_host_do_transaction ( sdspi_dev_handle_t handle , sdmmc_command_t * cmdinfo ) ;
2017-07-04 13:58:36 +08:00
/**
* @brief Set card clock frequency
*
* Currently only integer fractions of 40MHz clock can be used.
* For High Speed cards, 40MHz can be used.
* For Default Speed cards, 20MHz can be used.
*
* @note This function is not thread safe
*
2018-09-03 23:55:22 +08:00
* @param host Handle of the sdspi device
2017-07-04 13:58:36 +08:00
* @param freq_khz card clock frequency, in kHz
* @return
* - ESP_OK on success
* - other error codes may be returned in the future
*/
2018-09-03 23:55:22 +08:00
esp_err_t sdspi_host_set_card_clk ( sdspi_dev_handle_t host , uint32_t freq_khz ) ;
2017-07-04 13:58:36 +08:00
2022-07-13 00:00:46 +02:00
/**
* @brief Calculate working frequency for specific device
*
* @param handle SDSPI device handle
* @param[out] real_freq_khz output parameter to hold the calculated frequency (in kHz)
*
* @return
* - ESP_ERR_INVALID_ARG : ``handle`` is NULL or invalid or ``real_freq_khz`` parameter is NULL
* - ESP_OK : Success
*/
esp_err_t sdspi_host_get_real_freq ( sdspi_dev_handle_t handle , int * real_freq_khz ) ;
2017-07-04 13:58:36 +08:00
/**
* @brief Release resources allocated using sdspi_host_init
*
* @note This function is not thread safe
*
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_STATE if sdspi_host_init function has not been called
*/
2019-07-16 16:33:30 +07:00
esp_err_t sdspi_host_deinit ( void ) ;
2017-07-04 13:58:36 +08:00
2018-12-29 02:04:37 +08:00
/**
* @brief Enable SDIO interrupt.
*
2018-09-03 23:55:22 +08:00
* @param handle Handle of the sdspi device
2018-12-29 02:04:37 +08:00
*
* @return
* - ESP_OK on success
*/
2018-09-03 23:55:22 +08:00
esp_err_t sdspi_host_io_int_enable ( sdspi_dev_handle_t handle ) ;
2018-12-29 02:04:37 +08:00
/**
* @brief Wait for SDIO interrupt until timeout.
*
2018-09-03 23:55:22 +08:00
* @param handle Handle of the sdspi device
2018-12-29 02:04:37 +08:00
* @param timeout_ticks Ticks to wait before timeout.
*
* @return
* - ESP_OK on success
*/
2018-09-03 23:55:22 +08:00
esp_err_t sdspi_host_io_int_wait ( sdspi_dev_handle_t handle , TickType_t timeout_ticks ) ;
2024-03-29 11:36:27 +08:00
/**
* @brief Get the DMA memory information for the host driver
*
* @param[in] slot Not used
* @param[out] dma_mem_info DMA memory information structure
* @return
* - ESP_OK: ON success.
* - ESP_ERR_INVALID_ARG: Invalid argument.
*/
esp_err_t sdspi_host_get_dma_info ( int slot , esp_dma_mem_info_t * dma_mem_info ) ;
2017-07-04 13:58:36 +08:00
# ifdef __cplusplus
}
# endif