# SD SPI 主机驱动程序

[English]

## 概述

SD SPI 主机驱动程序支持使用 SPI 主控驱动程序与一或多张 SD 卡通信，SPI 主控驱动程序则利用 SPI 主机实现功能。每张 SD 卡都通过一个 SD SPI 设备访问，相应设备以 SD SPI 设备句柄 `sdspi_dev_handle_t` 表示。调用 `sdspi_host_init_device()` 将设备连接到 SPI 总线上时会返回所需 SPI 设备句柄。注意，在使用 SPI 总线前，需要先通过 `spi_bus_initialize()` 初始化总线。

SD SPI 主机驱动程序的命名模式参照 SDMMC 主机驱动，因为二者本身及支持的 API 都非常相似。

SD SPI 驱动程序使用 SPI 模式访问 SD 卡，此时的吞吐量较低，但可以更自由地选择管脚。通过 GPIO 矩阵，SPI 外设的信号可以路由到 ESP32 上的任意管脚。反之，若使用 SDMMC 主机驱动程序（请参阅 SDMMC 主机驱动）通过 SD 1 位/4 位模式访问 SD 卡，则可以实现更高的吞吐量，但需要使用专用的 IO_MUX 管脚路由信号。

SD SPI 主机驱动程序基于 SPI 主机驱动程序 实现。借助 SPI 主控驱动程序，SD 卡及其他 SPI 设备可以共享同一 SPI 总线。SPI 主机驱动程序将处理来自不同任务的独占访问。

SD SPI 驱动程序使用受软件控制的 CS 信号。

## 使用方法

首先，使用宏 `SDSPI_DEVICE_CONFIG_DEFAULT` 初始化结构体 `sdspi_device_config_t`，该结构体用于初始化 SD SPI 设备。该宏还会填充默认的管脚映射，与 SDMMC 主机驱动的管脚映射相同。随后根据需要，修改结构体中的主机和管脚配置。然后调用 `sdspi_host_init_device` 初始化 SD SPI 设备，并将其连接到所属的总线上。

接着，使用宏 `SDSPI_HOST_DEFAULT` 初始化结构体 `sdmmc_host_t`，该结构体用于存储上层（SD/SDIO/MMC 驱动）的状态和配置信息。将结构体中的 `slot` 参数设置为从 `sdspi_host_init_device` 返回的 SD SPI 设备的 SD SPI 句柄。使用 `sdmmc_host_t` 调用 `sdmmc_card_init`，检测并初始化 SD 卡。

初始化完成后，即可使用 SD/SDIO/MMC 驱动函数访问 SD 卡。

## 其他细节

通常，大多数应用程序仅使用驱动程序的以下 API 函数：

- `sdspi_host_init()`

- `sdspi_host_init_device()`

- `sdspi_host_remove_device()`

- `sdspi_host_deinit()`

对于其他函数，大多由协议层的 SD/SDIO/MMC 驱动程序通过 `sdmmc_host_t` 结构体中的函数指针使用。更多详情，请参阅 SD/SDIO/MMC 驱动程序。

备注

由于 SPI 驱动程序的限制，SD 卡在通过 SPI 总线与主设备进行数据传输和通信时，速度不超过 `SDMMC_FREQ_DEFAULT`。

警告

在 SD 卡之间以及其他 SPI 设备间共享 SPI 总线时，存在部分限制，详情请参阅 SD 卡与其他 SPI 设备共享 SPI 总线。

## 相关文档

- SD 卡与其他 SPI 设备共享 SPI 总线

## API 参考

### Header File

- components/esp_driver_sdspi/include/driver/sdspi_host.h

- This header file can be included with:

  >     #include "driver/sdspi_host.h"

- This header file is a part of the API provided by the `esp_driver_sdspi` component. To declare that your component depends on `esp_driver_sdspi`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_driver_sdspi

  > or

  >     PRIV_REQUIRES esp_driver_sdspi

### Functions

esp_err_t sdspi_host_init(void)

  Initialize SD SPI driver.

  备注

  This function is not thread safe

  返回:

    - ESP_OK on success

    - other error codes may be returned in future versions

esp_err_t sdspi_host_init_device(const sdspi_device_config_t *dev_config, sdspi_dev_handle_t *out_handle)

  Attach and initialize an SD SPI device on the specific SPI bus.

  备注

  This function is not thread safe

  备注

  Initialize the SPI bus by `spi_bus_initialize()` before calling this function.

  备注

  The SDIO over sdspi needs an extra interrupt line. Call `gpio_install_isr_service()` before this function.

  参数:

    - dev_config -- pointer to device configuration structure

    - out_handle -- Output of the handle to the sdspi device.

  返回:

    - ESP_OK on success

    - 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_remove_device(sdspi_dev_handle_t handle)

  Remove an SD SPI device.

  参数:

    handle -- Handle of the SD SPI device

  返回:

    Always ESP_OK

esp_err_t sdspi_host_do_transaction(sdspi_dev_handle_t handle, sdmmc_command_t *cmdinfo)

  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.

  备注

  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.

  参数:

    - handle -- Handle of the sdspi device

    - cmdinfo -- pointer to structure describing command and data to transfer

  返回:

    - 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_set_card_clk(sdspi_dev_handle_t host, uint32_t freq_khz)

  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.

  备注

  This function is not thread safe

  参数:

    - host -- Handle of the sdspi device

    - freq_khz -- card clock frequency, in kHz

  返回:

    - ESP_OK on success

    - other error codes may be returned in the future

esp_err_t sdspi_host_get_real_freq(sdspi_dev_handle_t handle, int *real_freq_khz)

  Calculate working frequency for specific device.

  参数:

    - handle -- SDSPI device handle

    - real_freq_khz -- [out] output parameter to hold the calculated frequency (in kHz)

  返回:

    - ESP_ERR_INVALID_ARG : `handle` is NULL or invalid or `real_freq_khz` parameter is NULL

    - ESP_OK : Success

esp_err_t sdspi_host_deinit(void)

  Release resources allocated using sdspi_host_init.

  备注

  This function is not thread safe

  返回:

    - ESP_OK on success

    - ESP_ERR_INVALID_STATE if sdspi_host_init function has not been called

esp_err_t sdspi_host_io_int_enable(sdspi_dev_handle_t handle)

  Enable SDIO interrupt.

  参数:

    handle -- Handle of the sdspi device

  返回:

    - ESP_OK on success

esp_err_t sdspi_host_io_int_wait(sdspi_dev_handle_t handle, uint32_t timeout_ticks)

  Wait for SDIO interrupt until timeout.

  参数:

    - handle -- Handle of the sdspi device

    - timeout_ticks -- Ticks to wait before timeout.

  返回:

    - ESP_OK on success

bool sdspi_host_check_buffer_alignment(int slot, const void *buf, size_t size)

  Check if the buffer meets the alignment requirements.

  参数:

    - slot -- [in] slot number (SDMMC_HOST_SLOT_0 or SDMMC_HOST_SLOT_1)

    - buf -- [in] buffer pointer

    - size -- [in] buffer size

  返回:

    True for aligned buffer, false for not aligned buffer

### Structures

struct sdspi_device_config_t

  Extra configuration for SD SPI device.

  Public Members

  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.

  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.

  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.

  int8_t wait_for_miso

    Timeout value in the driver will be waiting for MISO to be high before sending commands. Possible values are the following: 0: default value (40ms); -1: no waiting (0ms); 1-127: timeout in ms; else: invalid value, default will be used. This can be used to speed up transactions in certain scenarios but should not be needed if correct pull-up resistors are used. Use with care on devices where multiple SPI slaves use the same SPI bus.

### Macros

SDSPI_DEFAULT_HOST

SDSPI_DEFAULT_DMA

SDSPI_HOST_DEFAULT()

  Default sdmmc_host_t structure initializer for SD over SPI driver.

  Uses SPI mode and max frequency set to 20MHz

  'slot' should be set to an sdspi device initialized by `sdspi_host_init_device()`.

SDSPI_SLOT_NO_CS

  indicates that card select line is not used

SDSPI_SLOT_NO_CD

  indicates that card detect line is not used

SDSPI_SLOT_NO_WP

  indicates that write protect line is not used

SDSPI_SLOT_NO_INT

  indicates that interrupt line is not used

SDSPI_IO_ACTIVE_LOW

SDSPI_DEVICE_CONFIG_DEFAULT()

  Macro defining default configuration of SD SPI device.

### Type Definitions

typedef int sdspi_dev_handle_t

  Handle representing an SD SPI device.

此文档对您有帮助吗？

- 反馈已收到，谢谢！
- 如果您有其他意见，欢迎填写乐鑫文档反馈表。

- 我们重视您的反馈。
- 您可以填写乐鑫文档反馈表告诉我们如何改进该文档。