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 ;
2021-03-05 16:20:33 +08:00
# if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
# define SDSPI_DEFAULT_HOST HSPI_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 20 MHz
*
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 , \
. 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 , \
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 40 MHz clock can be used .
* For High Speed cards , 40 MHz can be used .
* For Default Speed cards , 20 MHz 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