2021-05-23 19:50:04 -04:00
|
|
|
/*
|
2024-03-28 23:36:27 -04:00
|
|
|
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
2021-05-23 19:50:04 -04:00
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
2017-07-04 01:58:36 -04:00
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <stddef.h>
|
|
|
|
#include "esp_err.h"
|
2023-11-16 02:17:04 -05:00
|
|
|
#include "sd_protocol_types.h"
|
2017-07-04 01:58:36 -04:00
|
|
|
#include "driver/gpio.h"
|
|
|
|
#include "driver/spi_master.h"
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
2018-09-03 11:55:22 -04:00
|
|
|
/// Handle representing an SD SPI device
|
|
|
|
typedef int sdspi_dev_handle_t;
|
|
|
|
|
2021-03-05 03:20:33 -05:00
|
|
|
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
|
|
|
|
#define SDSPI_DEFAULT_HOST HSPI_HOST
|
2022-02-08 12:38:06 -05:00
|
|
|
#define SDSPI_DEFAULT_DMA SDSPI_DEFAULT_HOST
|
2021-03-05 03:20:33 -05:00
|
|
|
#else
|
|
|
|
#define SDSPI_DEFAULT_HOST SPI2_HOST
|
2022-02-08 12:38:06 -05:00
|
|
|
#define SDSPI_DEFAULT_DMA SPI_DMA_CH_AUTO
|
2021-03-05 03:20:33 -05:00
|
|
|
#endif
|
|
|
|
|
2017-07-04 01:58:36 -04: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 11:55:22 -04:00
|
|
|
* 'slot' should be set to an sdspi device initialized by `sdspi_host_init_device()`.
|
2017-07-04 01:58:36 -04:00
|
|
|
*/
|
|
|
|
#define SDSPI_HOST_DEFAULT() {\
|
2018-09-03 11:55:22 -04:00
|
|
|
.flags = SDMMC_HOST_FLAG_SPI | SDMMC_HOST_FLAG_DEINIT_ARG, \
|
2021-03-05 03:20:33 -05:00
|
|
|
.slot = SDSPI_DEFAULT_HOST, \
|
2017-07-04 01:58:36 -04:00
|
|
|
.max_freq_khz = SDMMC_FREQ_DEFAULT, \
|
|
|
|
.io_voltage = 3.3f, \
|
|
|
|
.init = &sdspi_host_init, \
|
|
|
|
.set_bus_width = NULL, \
|
2018-04-23 02:35:13 -04:00
|
|
|
.get_bus_width = NULL, \
|
2018-08-22 06:16:32 -04:00
|
|
|
.set_bus_ddr_mode = NULL, \
|
2017-07-04 01:58:36 -04:00
|
|
|
.set_card_clk = &sdspi_host_set_card_clk, \
|
2022-09-19 15:15:23 -04:00
|
|
|
.set_cclk_always_on = NULL, \
|
2017-07-04 01:58:36 -04:00
|
|
|
.do_transaction = &sdspi_host_do_transaction, \
|
2018-09-03 11:55:22 -04:00
|
|
|
.deinit_p = &sdspi_host_remove_device, \
|
2018-12-28 13:04:37 -05:00
|
|
|
.io_int_enable = &sdspi_host_io_int_enable, \
|
|
|
|
.io_int_wait = &sdspi_host_io_int_wait, \
|
2017-11-07 23:52:25 -05:00
|
|
|
.command_timeout_ms = 0, \
|
2023-04-18 07:50:01 -04:00
|
|
|
.get_real_freq = &sdspi_host_get_real_freq, \
|
|
|
|
.input_delay_phase = SDMMC_DELAY_PHASE_0, \
|
2024-03-28 23:36:27 -04:00
|
|
|
.set_input_delay = NULL, \
|
|
|
|
.get_dma_info = &sdspi_host_get_dma_info, \
|
2017-07-04 01:58:36 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2018-09-03 11:55:22 -04:00
|
|
|
* Extra configuration for SD SPI device.
|
2017-07-04 01:58:36 -04:00
|
|
|
*/
|
|
|
|
typedef struct {
|
2018-09-03 11:55:22 -04:00
|
|
|
spi_host_device_t host_id; ///< SPI host to use, SPIx_HOST (see spi_types.h).
|
2023-06-15 03:22:07 -04: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 02:38:32 -04: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. */
|
2018-09-03 11:55:22 -04:00
|
|
|
} sdspi_device_config_t;
|
2017-07-04 01:58:36 -04:00
|
|
|
|
2023-06-15 03:22:07 -04: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 01:58:36 -04:00
|
|
|
|
|
|
|
/**
|
2018-09-03 11:55:22 -04:00
|
|
|
* Macro defining default configuration of SD SPI device.
|
2017-07-04 01:58:36 -04:00
|
|
|
*/
|
2018-09-03 11:55:22 -04:00
|
|
|
#define SDSPI_DEVICE_CONFIG_DEFAULT() {\
|
2021-03-05 03:20:33 -05:00
|
|
|
.host_id = SDSPI_DEFAULT_HOST, \
|
2017-07-04 01:58:36 -04:00
|
|
|
.gpio_cs = GPIO_NUM_13, \
|
2018-04-23 02:35:13 -04:00
|
|
|
.gpio_cd = SDSPI_SLOT_NO_CD, \
|
|
|
|
.gpio_wp = SDSPI_SLOT_NO_WP, \
|
2018-12-28 13:04:37 -05:00
|
|
|
.gpio_int = GPIO_NUM_NC, \
|
2023-06-15 03:22:07 -04:00
|
|
|
.gpio_wp_polarity = SDSPI_IO_ACTIVE_LOW, \
|
2017-07-04 01:58:36 -04: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 05:33:30 -04:00
|
|
|
esp_err_t sdspi_host_init(void);
|
2017-07-04 01:58:36 -04:00
|
|
|
|
|
|
|
/**
|
2018-09-03 11:55:22 -04:00
|
|
|
* @brief Attach and initialize an SD SPI device on the specific SPI bus
|
2017-07-04 01:58:36 -04:00
|
|
|
*
|
|
|
|
* @note This function is not thread safe
|
|
|
|
*
|
2018-09-03 11:55:22 -04:00
|
|
|
* @note Initialize the SPI bus by `spi_bus_initialize()` before calling this function.
|
2018-12-28 13:04:37 -05:00
|
|
|
*
|
2018-09-03 11:55:22 -04:00
|
|
|
* @note The SDIO over sdspi needs an extra interrupt line. Call ``gpio_install_isr_service()`` before this function.
|
2017-07-04 01:58:36 -04:00
|
|
|
*
|
2018-09-03 11:55:22 -04:00
|
|
|
* @param dev_config pointer to device configuration structure
|
|
|
|
* @param out_handle Output of the handle to the sdspi device.
|
|
|
|
|
2017-07-04 01:58:36 -04:00
|
|
|
* @return
|
|
|
|
* - ESP_OK on success
|
2018-09-03 11:55:22 -04:00
|
|
|
* - ESP_ERR_INVALID_ARG if sdspi_host_init_device has invalid arguments
|
2017-07-04 01:58:36 -04:00
|
|
|
* - ESP_ERR_NO_MEM if memory can not be allocated
|
|
|
|
* - other errors from the underlying spi_master and gpio drivers
|
|
|
|
*/
|
2018-09-03 11:55:22 -04: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 01:58:36 -04: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 11:55:22 -04:00
|
|
|
* @param handle Handle of the sdspi device
|
2017-07-04 01:58:36 -04: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 11:55:22 -04:00
|
|
|
esp_err_t sdspi_host_do_transaction(sdspi_dev_handle_t handle, sdmmc_command_t *cmdinfo);
|
2017-07-04 01:58:36 -04: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 11:55:22 -04:00
|
|
|
* @param host Handle of the sdspi device
|
2017-07-04 01:58:36 -04: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 11:55:22 -04:00
|
|
|
esp_err_t sdspi_host_set_card_clk(sdspi_dev_handle_t host, uint32_t freq_khz);
|
2017-07-04 01:58:36 -04:00
|
|
|
|
2022-07-12 18:00:46 -04: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 01:58:36 -04: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 05:33:30 -04:00
|
|
|
esp_err_t sdspi_host_deinit(void);
|
2017-07-04 01:58:36 -04:00
|
|
|
|
2018-12-28 13:04:37 -05:00
|
|
|
/**
|
|
|
|
* @brief Enable SDIO interrupt.
|
|
|
|
*
|
2018-09-03 11:55:22 -04:00
|
|
|
* @param handle Handle of the sdspi device
|
2018-12-28 13:04:37 -05:00
|
|
|
*
|
|
|
|
* @return
|
|
|
|
* - ESP_OK on success
|
|
|
|
*/
|
2018-09-03 11:55:22 -04:00
|
|
|
esp_err_t sdspi_host_io_int_enable(sdspi_dev_handle_t handle);
|
2018-12-28 13:04:37 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Wait for SDIO interrupt until timeout.
|
|
|
|
*
|
2018-09-03 11:55:22 -04:00
|
|
|
* @param handle Handle of the sdspi device
|
2018-12-28 13:04:37 -05:00
|
|
|
* @param timeout_ticks Ticks to wait before timeout.
|
|
|
|
*
|
|
|
|
* @return
|
|
|
|
* - ESP_OK on success
|
|
|
|
*/
|
2018-09-03 11:55:22 -04:00
|
|
|
esp_err_t sdspi_host_io_int_wait(sdspi_dev_handle_t handle, TickType_t timeout_ticks);
|
|
|
|
|
2024-03-28 23:36:27 -04: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 01:58:36 -04:00
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|