spi_common.h 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. /*
  2. * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #pragma once
  7. #include <stdint.h>
  8. #include <stdbool.h>
  9. #include "sdkconfig.h"
  10. #include "esp_err.h"
  11. #include "esp_ipc.h"
  12. #include "esp_intr_types.h"
  13. #include "hal/spi_types.h"
  14. #ifdef __cplusplus
  15. extern "C"
  16. {
  17. #endif
  18. //Maximum amount of bytes that can be put in one DMA descriptor
  19. #define SPI_MAX_DMA_LEN (4096-4)
  20. /**
  21. * Transform unsigned integer of length <= 32 bits to the format which can be
  22. * sent by the SPI driver directly.
  23. *
  24. * E.g. to send 9 bits of data, you can:
  25. *
  26. * uint16_t data = SPI_SWAP_DATA_TX(0x145, 9);
  27. *
  28. * Then points tx_buffer to ``&data``.
  29. *
  30. * @param DATA Data to be sent, can be uint8_t, uint16_t or uint32_t.
  31. * @param LEN Length of data to be sent, since the SPI peripheral sends from
  32. * the MSB, this helps to shift the data to the MSB.
  33. */
  34. #define SPI_SWAP_DATA_TX(DATA, LEN) __builtin_bswap32((uint32_t)(DATA)<<(32-(LEN)))
  35. /**
  36. * Transform received data of length <= 32 bits to the format of an unsigned integer.
  37. *
  38. * E.g. to transform the data of 15 bits placed in a 4-byte array to integer:
  39. *
  40. * uint16_t data = SPI_SWAP_DATA_RX(*(uint32_t*)t->rx_data, 15);
  41. *
  42. * @param DATA Data to be rearranged, can be uint8_t, uint16_t or uint32_t.
  43. * @param LEN Length of data received, since the SPI peripheral writes from
  44. * the MSB, this helps to shift the data to the LSB.
  45. */
  46. #define SPI_SWAP_DATA_RX(DATA, LEN) (__builtin_bswap32(DATA)>>(32-(LEN)))
  47. #define SPICOMMON_BUSFLAG_SLAVE 0 ///< Initialize I/O in slave mode
  48. #define SPICOMMON_BUSFLAG_MASTER (1<<0) ///< Initialize I/O in master mode
  49. #define SPICOMMON_BUSFLAG_IOMUX_PINS (1<<1) ///< Check using iomux pins. Or indicates the pins are configured through the IO mux rather than GPIO matrix.
  50. #define SPICOMMON_BUSFLAG_GPIO_PINS (1<<2) ///< Force the signals to be routed through GPIO matrix. Or indicates the pins are routed through the GPIO matrix.
  51. #define SPICOMMON_BUSFLAG_SCLK (1<<3) ///< Check existing of SCLK pin. Or indicates CLK line initialized.
  52. #define SPICOMMON_BUSFLAG_MISO (1<<4) ///< Check existing of MISO pin. Or indicates MISO line initialized.
  53. #define SPICOMMON_BUSFLAG_MOSI (1<<5) ///< Check existing of MOSI pin. Or indicates MOSI line initialized.
  54. #define SPICOMMON_BUSFLAG_DUAL (1<<6) ///< Check MOSI and MISO pins can output. Or indicates bus able to work under DIO mode.
  55. #define SPICOMMON_BUSFLAG_WPHD (1<<7) ///< Check existing of WP and HD pins. Or indicates WP & HD pins initialized.
  56. #define SPICOMMON_BUSFLAG_QUAD (SPICOMMON_BUSFLAG_DUAL|SPICOMMON_BUSFLAG_WPHD) ///< Check existing of MOSI/MISO/WP/HD pins as output. Or indicates bus able to work under QIO mode.
  57. #define SPICOMMON_BUSFLAG_IO4_IO7 (1<<8) ///< Check existing of IO4~IO7 pins. Or indicates IO4~IO7 pins initialized.
  58. #define SPICOMMON_BUSFLAG_OCTAL (SPICOMMON_BUSFLAG_QUAD|SPICOMMON_BUSFLAG_IO4_IO7) ///< Check existing of MOSI/MISO/WP/HD/SPIIO4/SPIIO5/SPIIO6/SPIIO7 pins as output. Or indicates bus able to work under octal mode.
  59. #define SPICOMMON_BUSFLAG_NATIVE_PINS SPICOMMON_BUSFLAG_IOMUX_PINS
  60. /**
  61. * @brief SPI DMA channels
  62. */
  63. typedef enum {
  64. SPI_DMA_DISABLED = 0, ///< Do not enable DMA for SPI
  65. #if CONFIG_IDF_TARGET_ESP32
  66. SPI_DMA_CH1 = 1, ///< Enable DMA, select DMA Channel 1
  67. SPI_DMA_CH2 = 2, ///< Enable DMA, select DMA Channel 2
  68. #endif
  69. SPI_DMA_CH_AUTO = 3, ///< Enable DMA, channel is automatically selected by driver
  70. } spi_common_dma_t;
  71. #if __cplusplus
  72. /* Needed for C++ backwards compatibility with earlier ESP-IDF where this argument is a bare 'int'. Can be removed in ESP-IDF 5 */
  73. typedef int spi_dma_chan_t;
  74. #else
  75. typedef spi_common_dma_t spi_dma_chan_t;
  76. #endif
  77. /**
  78. * @brief This is a configuration structure for a SPI bus.
  79. *
  80. * You can use this structure to specify the GPIO pins of the bus. Normally, the driver will use the
  81. * GPIO matrix to route the signals. An exception is made when all signals either can be routed through
  82. * the IO_MUX or are -1. In that case, the IO_MUX is used, allowing for >40MHz speeds.
  83. *
  84. * @note Be advised that the slave driver does not use the quadwp/quadhd lines and fields in spi_bus_config_t refering to these lines will be ignored and can thus safely be left uninitialized.
  85. */
  86. typedef struct {
  87. union {
  88. int mosi_io_num; ///< GPIO pin for Master Out Slave In (=spi_d) signal, or -1 if not used.
  89. int data0_io_num; ///< GPIO pin for spi data0 signal in quad/octal mode, or -1 if not used.
  90. };
  91. union {
  92. int miso_io_num; ///< GPIO pin for Master In Slave Out (=spi_q) signal, or -1 if not used.
  93. int data1_io_num; ///< GPIO pin for spi data1 signal in quad/octal mode, or -1 if not used.
  94. };
  95. int sclk_io_num; ///< GPIO pin for SPI Clock signal, or -1 if not used.
  96. union {
  97. int quadwp_io_num; ///< GPIO pin for WP (Write Protect) signal, or -1 if not used.
  98. int data2_io_num; ///< GPIO pin for spi data2 signal in quad/octal mode, or -1 if not used.
  99. };
  100. union {
  101. int quadhd_io_num; ///< GPIO pin for HD (Hold) signal, or -1 if not used.
  102. int data3_io_num; ///< GPIO pin for spi data3 signal in quad/octal mode, or -1 if not used.
  103. };
  104. int data4_io_num; ///< GPIO pin for spi data4 signal in octal mode, or -1 if not used.
  105. int data5_io_num; ///< GPIO pin for spi data5 signal in octal mode, or -1 if not used.
  106. int data6_io_num; ///< GPIO pin for spi data6 signal in octal mode, or -1 if not used.
  107. int data7_io_num; ///< GPIO pin for spi data7 signal in octal mode, or -1 if not used.
  108. int max_transfer_sz; ///< Maximum transfer size, in bytes. Defaults to 4092 if 0 when DMA enabled, or to `SOC_SPI_MAXIMUM_BUFFER_SIZE` if DMA is disabled.
  109. uint32_t flags; ///< Abilities of bus to be checked by the driver. Or-ed value of ``SPICOMMON_BUSFLAG_*`` flags.
  110. esp_intr_cpu_affinity_t isr_cpu_id; ///< Select cpu core to register SPI ISR.
  111. int intr_flags; /**< Interrupt flag for the bus to set the priority, and IRAM attribute, see
  112. * ``esp_intr_alloc.h``. Note that the EDGE, INTRDISABLED attribute are ignored
  113. * by the driver. Note that if ESP_INTR_FLAG_IRAM is set, ALL the callbacks of
  114. * the driver, and their callee functions, should be put in the IRAM.
  115. */
  116. } spi_bus_config_t;
  117. /**
  118. * @brief Initialize a SPI bus
  119. *
  120. * @warning SPI0/1 is not supported
  121. *
  122. * @param host_id SPI peripheral that controls this bus
  123. * @param bus_config Pointer to a spi_bus_config_t struct specifying how the host should be initialized
  124. * @param dma_chan - Selecting a DMA channel for an SPI bus allows transactions on the bus with size only limited by the amount of internal memory.
  125. * - Selecting SPI_DMA_DISABLED limits the size of transactions.
  126. * - Set to SPI_DMA_DISABLED if only the SPI flash uses this bus.
  127. * - Set to SPI_DMA_CH_AUTO to let the driver to allocate the DMA channel.
  128. *
  129. * @warning If a DMA channel is selected, any transmit and receive buffer used should be allocated in
  130. * DMA-capable memory.
  131. *
  132. * @warning The ISR of SPI is always executed on the core which calls this
  133. * function. Never starve the ISR on this core or the SPI transactions will not
  134. * be handled.
  135. *
  136. * @return
  137. * - ESP_ERR_INVALID_ARG if configuration is invalid
  138. * - ESP_ERR_INVALID_STATE if host already is in use
  139. * - ESP_ERR_NOT_FOUND if there is no available DMA channel
  140. * - ESP_ERR_NO_MEM if out of memory
  141. * - ESP_OK on success
  142. */
  143. esp_err_t spi_bus_initialize(spi_host_device_t host_id, const spi_bus_config_t *bus_config, spi_dma_chan_t dma_chan);
  144. /**
  145. * @brief Free a SPI bus
  146. *
  147. * @warning In order for this to succeed, all devices have to be removed first.
  148. *
  149. * @param host_id SPI peripheral to free
  150. * @return
  151. * - ESP_ERR_INVALID_ARG if parameter is invalid
  152. * - ESP_ERR_INVALID_STATE if bus hasn't been initialized before, or not all devices on the bus are freed
  153. * - ESP_OK on success
  154. */
  155. esp_err_t spi_bus_free(spi_host_device_t host_id);
  156. #ifdef __cplusplus
  157. }
  158. #endif