Skip to content

Commit

Permalink
sdspi, vfs_fat: allow sharing SPI bus among devices, and mounting mul…
Browse files Browse the repository at this point in the history
…tiple SD cards
  • Loading branch information
ginkgm committed Feb 12, 2020
1 parent 278634d commit 067f3d2
Show file tree
Hide file tree
Showing 17 changed files with 1,033 additions and 390 deletions.
6 changes: 5 additions & 1 deletion components/driver/include/driver/sdmmc_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ typedef struct {
#define SDMMC_HOST_FLAG_8BIT BIT(2) /*!< host supports 8-line MMC protocol */
#define SDMMC_HOST_FLAG_SPI BIT(3) /*!< host supports SPI protocol */
#define SDMMC_HOST_FLAG_DDR BIT(4) /*!< host supports DDR mode for SD/MMC */
#define SDMMC_HOST_FLAG_DEINIT_ARG BIT(5) /*!< host `deinit` function called with the slot argument */
int slot; /*!< slot number, to be passed to host functions */
int max_freq_khz; /*!< max frequency supported by the host */
#define SDMMC_FREQ_DEFAULT 20000 /*!< SD/MMC Default speed (limited by clock divider) */
Expand All @@ -144,7 +145,10 @@ typedef struct {
esp_err_t (*set_bus_ddr_mode)(int slot, bool ddr_enable); /*!< host function to set DDR mode */
esp_err_t (*set_card_clk)(int slot, uint32_t freq_khz); /*!< host function to set card clock frequency */
esp_err_t (*do_transaction)(int slot, sdmmc_command_t* cmdinfo); /*!< host function to do a transaction */
esp_err_t (*deinit)(void); /*!< host function to deinitialize the driver */
union {
esp_err_t (*deinit)(void); /*!< host function to deinitialize the driver */
esp_err_t (*deinit_p)(int slot); /*!< host function to deinitialize the driver, called with the `slot` */
};
esp_err_t (*io_int_enable)(int slot); /*!< Host function to enable SDIO interrupt line */
esp_err_t (*io_int_wait)(int slot, TickType_t timeout_ticks); /*!< Host function to wait for SDIO interrupt line to be active */
int command_timeout_ms; /*!< timeout, in milliseconds, of a single command. Set to 0 to use the default value. */
Expand Down
120 changes: 90 additions & 30 deletions components/driver/include/driver/sdspi_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,18 @@
extern "C" {
#endif

/// Handle representing an SD SPI device
typedef int sdspi_dev_handle_t;

/**
* @brief Default sdmmc_host_t structure initializer for SD over SPI driver
*
* Uses SPI mode and max frequency set to 20MHz
*
* 'slot' can be set to one of HSPI_HOST, VSPI_HOST.
* 'slot' should be set to an sdspi device initialized by `sdspi_host_init_device()`.
*/
#define SDSPI_HOST_DEFAULT() {\
.flags = SDMMC_HOST_FLAG_SPI, \
.flags = SDMMC_HOST_FLAG_SPI | SDMMC_HOST_FLAG_DEINIT_ARG, \
.slot = HSPI_HOST, \
.max_freq_khz = SDMMC_FREQ_DEFAULT, \
.io_voltage = 3.3f, \
Expand All @@ -43,42 +46,36 @@ extern "C" {
.set_bus_ddr_mode = NULL, \
.set_card_clk = &sdspi_host_set_card_clk, \
.do_transaction = &sdspi_host_do_transaction, \
.deinit = &sdspi_host_deinit, \
.deinit_p = &sdspi_host_remove_device, \
.io_int_enable = &sdspi_host_io_int_enable, \
.io_int_wait = &sdspi_host_io_int_wait, \
.command_timeout_ms = 0, \
}

/**
* Extra configuration for SPI host
* Extra configuration for SD SPI device.
*/
typedef struct {
gpio_num_t gpio_miso; ///< GPIO number of MISO signal
gpio_num_t gpio_mosi; ///< GPIO number of MOSI signal
gpio_num_t gpio_sck; ///< GPIO number of SCK signal
spi_host_device_t host_id; ///< SPI host to use, SPIx_HOST (see spi_types.h).
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.
int dma_channel; ///< DMA channel to be used by SPI driver (1 or 2)
} sdspi_slot_config_t;
} sdspi_device_config_t;

#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

/**
* Macro defining default configuration of SPI host
* Macro defining default configuration of SD SPI device.
*/
#define SDSPI_SLOT_CONFIG_DEFAULT() {\
.gpio_miso = GPIO_NUM_2, \
.gpio_mosi = GPIO_NUM_15, \
.gpio_sck = GPIO_NUM_14, \
#define SDSPI_DEVICE_CONFIG_DEFAULT() {\
.host_id = HSPI_HOST, \
.gpio_cs = GPIO_NUM_13, \
.gpio_cd = SDSPI_SLOT_NO_CD, \
.gpio_wp = SDSPI_SLOT_NO_WP, \
.gpio_int = GPIO_NUM_NC, \
.dma_channel = 1 \
}

/**
Expand All @@ -93,22 +90,32 @@ typedef struct {
esp_err_t sdspi_host_init(void);

/**
* @brief Initialize SD SPI driver for the specific SPI controller
* @brief Attach and initialize an SD SPI device on the specific SPI bus
*
* @note This function is not thread safe
*
* @note The SDIO over sdspi needs an extra interrupt line. Call ``gpio_install_isr_service()`` before this function.
* @note Initialize the SPI bus by `spi_bus_initialize()` before calling this function.
*
* @param slot SPI controller to use (HSPI_HOST or VSPI_HOST)
* @param slot_config pointer to slot configuration structure
* @note The SDIO over sdspi needs an extra interrupt line. Call ``gpio_install_isr_service()`` before this function.
*
* @param dev_config pointer to device configuration structure
* @param out_handle Output of the handle to the sdspi device.
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if sdspi_init_slot has invalid arguments
* - ESP_ERR_INVALID_ARG if sdspi_host_init_device has invalid arguments
* - ESP_ERR_NO_MEM if memory can not be allocated
* - other errors from the underlying spi_master and gpio drivers
*/
esp_err_t sdspi_host_init_slot(int slot, const sdspi_slot_config_t* slot_config);
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);

/**
* @brief Send command to the card and get response
Expand All @@ -121,15 +128,15 @@ esp_err_t sdspi_host_init_slot(int slot, const sdspi_slot_config_t* slot_config)
* can call sdspi_host_do_transaction as long as other sdspi_host_*
* functions are not called.
*
* @param slot SPI controller (HSPI_HOST or VSPI_HOST)
* @param handle Handle of the sdspi device
* @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
*/
esp_err_t sdspi_host_do_transaction(int slot, sdmmc_command_t *cmdinfo);
esp_err_t sdspi_host_do_transaction(sdspi_dev_handle_t handle, sdmmc_command_t *cmdinfo);

/**
* @brief Set card clock frequency
Expand All @@ -140,14 +147,13 @@ esp_err_t sdspi_host_do_transaction(int slot, sdmmc_command_t *cmdinfo);
*
* @note This function is not thread safe
*
* @param slot SPI controller (HSPI_HOST or VSPI_HOST)
* @param host Handle of the sdspi device
* @param freq_khz card clock frequency, in kHz
* @return
* - ESP_OK on success
* - other error codes may be returned in the future
*/
esp_err_t sdspi_host_set_card_clk(int slot, uint32_t freq_khz);

esp_err_t sdspi_host_set_card_clk(sdspi_dev_handle_t host, uint32_t freq_khz);

/**
* @brief Release resources allocated using sdspi_host_init
Expand All @@ -163,23 +169,77 @@ esp_err_t sdspi_host_deinit(void);
/**
* @brief Enable SDIO interrupt.
*
* @param slot SPI controller to use (HSPI_HOST or VSPI_HOST)
* @param handle Handle of the sdspi device
*
* @return
* - ESP_OK on success
*/
esp_err_t sdspi_host_io_int_enable(int slot);
esp_err_t sdspi_host_io_int_enable(sdspi_dev_handle_t handle);

/**
* @brief Wait for SDIO interrupt until timeout.
*
* @param slot SPI controller to use (HSPI_HOST or VSPI_HOST)
* @param handle Handle of the sdspi device
* @param timeout_ticks Ticks to wait before timeout.
*
* @return
* - ESP_OK on success
*/
esp_err_t sdspi_host_io_int_wait(int slot, TickType_t timeout_ticks);
esp_err_t sdspi_host_io_int_wait(sdspi_dev_handle_t handle, TickType_t timeout_ticks);

/*******************************************************************************
* Deprecated APIs
******************************************************************************/

/**
* Extra configuration for SPI host.
*
* @deprecated Use `sdspi_device_config_t` and corresponding `sdspi_host_init_device()` instead.
*/
typedef struct {
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.
gpio_num_t gpio_miso; ///< GPIO number of MISO signal.
gpio_num_t gpio_mosi; ///< GPIO number of MOSI signal.
gpio_num_t gpio_sck; ///< GPIO number of SCK signal.
int dma_channel; ///< DMA channel to be used by SPI driver (1 or 2).
} sdspi_slot_config_t;

/**
* Macro defining default configuration of SPI host
*/
#define SDSPI_SLOT_CONFIG_DEFAULT() {\
.gpio_cs = GPIO_NUM_13, \
.gpio_cd = SDSPI_SLOT_NO_CD, \
.gpio_wp = SDSPI_SLOT_NO_WP, \
.gpio_int = GPIO_NUM_NC, \
.gpio_miso = GPIO_NUM_2, \
.gpio_mosi = GPIO_NUM_15, \
.gpio_sck = GPIO_NUM_14, \
.dma_channel = 1, \
}

/**
* @brief Initialize SD SPI driver for the specific SPI controller
*
* @note This function is not thread safe
*
* @note The SDIO over sdspi needs an extra interrupt line. Call ``gpio_install_isr_service()`` before this function.
*
* @param slot SPI controller to use (HSPI_HOST or VSPI_HOST)
* @param slot_config pointer to slot configuration structure
* @deprecated Use `sdspi_host_init_device` instead.
*
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if sdspi_init_slot has invalid arguments
* - ESP_ERR_NO_MEM if memory can not be allocated
* - other errors from the underlying spi_master and gpio drivers
*/
esp_err_t sdspi_host_init_slot(int slot, const sdspi_slot_config_t* slot_config);

#ifdef __cplusplus
}
Expand Down
Loading

0 comments on commit 067f3d2

Please sign in to comment.