spi_slave_hd.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /*
  2. * SPDX-FileCopyrightText: 2010-2021 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #pragma once
  7. #include "esp_types.h"
  8. #include "soc/soc_caps.h"
  9. #include "freertos/FreeRTOS.h"
  10. #include "hal/spi_types.h"
  11. #include "driver/spi_common.h"
  12. #include "sdkconfig.h"
  13. #ifdef __cplusplus
  14. extern "C"
  15. {
  16. #endif
  17. #if !SOC_SPI_SUPPORT_SLAVE_HD_VER2 && !CI_HEADER_CHECK
  18. #error The SPI peripheral does not support this feature
  19. #endif
  20. #define SPI_SLAVE_HD_TRANS_DMA_BUFFER_ALIGN_AUTO (1<<0) ///< Automatically re-malloc dma buffer if user buffer doesn't meet hardware alignment or dma_capable, this process may lose some memory and performance
  21. /// Descriptor of data to send/receive
  22. typedef struct {
  23. uint8_t* data; ///< Buffer to send, must be DMA capable
  24. size_t len; ///< Len of data to send/receive. For receiving the buffer length should be multiples of 4 bytes, otherwise the extra part will be truncated.
  25. size_t trans_len; ///< For RX direction, it indicates the data actually received. For TX direction, it is meaningless.
  26. uint32_t flags; ///< Bitwise OR of SPI_SLAVE_HD_TRANS_* flags
  27. void* arg; ///< Extra argument indiciating this data
  28. } spi_slave_hd_data_t;
  29. /// Information of SPI Slave HD event
  30. typedef struct {
  31. spi_event_t event; ///< Event type
  32. spi_slave_hd_data_t* trans; ///< Corresponding transaction for SPI_EV_SEND and SPI_EV_RECV events
  33. } spi_slave_hd_event_t;
  34. /// Callback for SPI Slave HD
  35. typedef bool (*slave_cb_t)(void* arg, spi_slave_hd_event_t* event, BaseType_t* awoken);
  36. /// Channel of SPI Slave HD to do data transaction
  37. typedef enum {
  38. SPI_SLAVE_CHAN_TX = 0, ///< The output channel (RDDMA)
  39. SPI_SLAVE_CHAN_RX = 1, ///< The input channel (WRDMA)
  40. } spi_slave_chan_t;
  41. /// Callback configuration structure for SPI Slave HD
  42. typedef struct {
  43. slave_cb_t cb_buffer_tx; ///< Callback when master reads from shared buffer
  44. slave_cb_t cb_buffer_rx; ///< Callback when master writes to shared buffer
  45. slave_cb_t cb_send_dma_ready; ///< Callback when TX data buffer is loaded to the hardware (DMA)
  46. slave_cb_t cb_sent; ///< Callback when data are sent
  47. slave_cb_t cb_recv_dma_ready; ///< Callback when RX data buffer is loaded to the hardware (DMA)
  48. slave_cb_t cb_recv; ///< Callback when data are received
  49. slave_cb_t cb_cmd9; ///< Callback when CMD9 received
  50. slave_cb_t cb_cmdA; ///< Callback when CMDA received
  51. void* arg; ///< Argument indicating this SPI Slave HD peripheral instance
  52. } spi_slave_hd_callback_config_t;
  53. //flags for ``spi_slave_hd_slot_config_t`` to use
  54. #define SPI_SLAVE_HD_TXBIT_LSBFIRST (1<<0) ///< Transmit command/address/data LSB first instead of the default MSB first
  55. #define SPI_SLAVE_HD_RXBIT_LSBFIRST (1<<1) ///< Receive data LSB first instead of the default MSB first
  56. #define SPI_SLAVE_HD_BIT_LSBFIRST (SPI_SLAVE_HD_TXBIT_LSBFIRST|SPI_SLAVE_HD_RXBIT_LSBFIRST) ///< Transmit and receive LSB first
  57. #define SPI_SLAVE_HD_APPEND_MODE (1<<2) ///< Adopt DMA append mode for transactions. In this mode, users can load(append) DMA descriptors without stopping the DMA
  58. /// Configuration structure for the SPI Slave HD driver
  59. typedef struct {
  60. uint8_t mode; /**< SPI mode, representing a pair of (CPOL, CPHA) configuration:
  61. - 0: (0, 0)
  62. - 1: (0, 1)
  63. - 2: (1, 0)
  64. - 3: (1, 1)
  65. */
  66. uint32_t spics_io_num; ///< CS GPIO pin for this device
  67. uint32_t flags; ///< Bitwise OR of SPI_SLAVE_HD_* flags
  68. uint32_t command_bits; ///< command field bits, multiples of 8 and at least 8.
  69. uint32_t address_bits; ///< address field bits, multiples of 8 and at least 8.
  70. uint32_t dummy_bits; ///< dummy field bits, multiples of 8 and at least 8.
  71. uint32_t queue_size; ///< Transaction queue size. This sets how many transactions can be 'in the air' (queued using spi_slave_hd_queue_trans but not yet finished using spi_slave_hd_get_trans_result) at the same time
  72. spi_dma_chan_t dma_chan; ///< DMA channel to used.
  73. spi_slave_hd_callback_config_t cb_config; ///< Callback configuration
  74. } spi_slave_hd_slot_config_t;
  75. /**
  76. * @brief Initialize the SPI Slave HD driver.
  77. *
  78. * @param host_id The host to use
  79. * @param bus_config Bus configuration for the bus used
  80. * @param config Configuration for the SPI Slave HD driver
  81. * @return
  82. * - ESP_OK: on success
  83. * - ESP_ERR_INVALID_ARG: invalid argument given
  84. * - ESP_ERR_INVALID_STATE: function called in invalid state, may be some resources are already in use
  85. * - ESP_ERR_NOT_FOUND if there is no available DMA channel
  86. * - ESP_ERR_NO_MEM: memory allocation failed
  87. * - or other return value from `esp_intr_alloc`
  88. */
  89. esp_err_t spi_slave_hd_init(spi_host_device_t host_id, const spi_bus_config_t *bus_config,
  90. const spi_slave_hd_slot_config_t *config);
  91. /**
  92. * @brief Deinitialize the SPI Slave HD driver
  93. *
  94. * @param host_id The host to deinitialize the driver
  95. * @return
  96. * - ESP_OK: on success
  97. * - ESP_ERR_INVALID_ARG: if the host_id is not correct
  98. */
  99. esp_err_t spi_slave_hd_deinit(spi_host_device_t host_id);
  100. /**
  101. * @brief Queue transactions (segment mode)
  102. *
  103. * @param host_id Host to queue the transaction
  104. * @param chan SPI_SLAVE_CHAN_TX or SPI_SLAVE_CHAN_RX
  105. * @param trans Transaction descriptors
  106. * @param timeout Timeout before the data is queued
  107. * @return
  108. * - ESP_OK: on success
  109. * - ESP_ERR_INVALID_ARG: The input argument is invalid. Can be the following reason:
  110. * - The buffer given is not DMA capable
  111. * - The length of data is invalid (not larger than 0, or exceed the max transfer length)
  112. * - The transaction direction is invalid
  113. * - ESP_ERR_TIMEOUT: Cannot queue the data before timeout. Master is still processing previous transaction.
  114. * - ESP_ERR_INVALID_STATE: Function called in invalid state. This API should be called under segment mode.
  115. */
  116. esp_err_t spi_slave_hd_queue_trans(spi_host_device_t host_id, spi_slave_chan_t chan, spi_slave_hd_data_t* trans, TickType_t timeout);
  117. /**
  118. * @brief Get the result of a data transaction (segment mode)
  119. *
  120. * @note This API should be called successfully the same times as the ``spi_slave_hd_queue_trans``.
  121. *
  122. * @param host_id Host to queue the transaction
  123. * @param chan Channel to get the result, SPI_SLAVE_CHAN_TX or SPI_SLAVE_CHAN_RX
  124. * @param[out] out_trans Pointer to the transaction descriptor (``spi_slave_hd_data_t``) passed to the driver before. Hardware has finished this transaction. Member ``trans_len`` indicates the actual number of bytes of received data, it's meaningless for TX.
  125. * @param timeout Timeout before the result is got
  126. * @return
  127. * - ESP_OK: on success
  128. * - ESP_ERR_INVALID_ARG: Function is not valid
  129. * - ESP_ERR_TIMEOUT: There's no transaction done before timeout
  130. * - ESP_ERR_INVALID_STATE: Function called in invalid state. This API should be called under segment mode.
  131. */
  132. esp_err_t spi_slave_hd_get_trans_res(spi_host_device_t host_id, spi_slave_chan_t chan, spi_slave_hd_data_t **out_trans, TickType_t timeout);
  133. /**
  134. * @brief Read the shared registers
  135. *
  136. * @param host_id Host to read the shared registers
  137. * @param addr Address of register to read, 0 to ``SOC_SPI_MAXIMUM_BUFFER_SIZE-1``
  138. * @param[out] out_data Output buffer to store the read data
  139. * @param len Length to read, not larger than ``SOC_SPI_MAXIMUM_BUFFER_SIZE-addr``
  140. */
  141. void spi_slave_hd_read_buffer(spi_host_device_t host_id, int addr, uint8_t *out_data, size_t len);
  142. /**
  143. * @brief Write the shared registers
  144. *
  145. * @param host_id Host to write the shared registers
  146. * @param addr Address of register to write, 0 to ``SOC_SPI_MAXIMUM_BUFFER_SIZE-1``
  147. * @param data Buffer holding the data to write
  148. * @param len Length to write, ``SOC_SPI_MAXIMUM_BUFFER_SIZE-addr``
  149. */
  150. void spi_slave_hd_write_buffer(spi_host_device_t host_id, int addr, uint8_t *data, size_t len);
  151. /**
  152. * @brief Load transactions (append mode)
  153. *
  154. * @note In this mode, user transaction descriptors will be appended to the DMA and the DMA will keep processing the data without stopping
  155. *
  156. * @param host_id Host to load transactions
  157. * @param chan SPI_SLAVE_CHAN_TX or SPI_SLAVE_CHAN_RX
  158. * @param trans Transaction descriptor
  159. * @param timeout Timeout before the transaction is loaded
  160. * @return
  161. * - ESP_OK: on success
  162. * - ESP_ERR_INVALID_ARG: The input argument is invalid. Can be the following reason:
  163. * - The buffer given is not DMA capable
  164. * - The length of data is invalid (not larger than 0, or exceed the max transfer length)
  165. * - The transaction direction is invalid
  166. * - ESP_ERR_TIMEOUT: Master is still processing previous transaction. There is no available transaction for slave to load
  167. * - ESP_ERR_INVALID_STATE: Function called in invalid state. This API should be called under append mode.
  168. */
  169. esp_err_t spi_slave_hd_append_trans(spi_host_device_t host_id, spi_slave_chan_t chan, spi_slave_hd_data_t *trans, TickType_t timeout);
  170. /**
  171. * @brief Get the result of a data transaction (append mode)
  172. *
  173. * @note This API should be called the same times as the ``spi_slave_hd_append_trans``
  174. *
  175. * @param host_id Host to load the transaction
  176. * @param chan SPI_SLAVE_CHAN_TX or SPI_SLAVE_CHAN_RX
  177. * @param[out] out_trans Pointer to the transaction descriptor (``spi_slave_hd_data_t``) passed to the driver before. Hardware has finished this transaction. Member ``trans_len`` indicates the actual number of bytes of received data, it's meaningless for TX.
  178. * @param timeout Timeout before the result is got
  179. * @return
  180. * - ESP_OK: on success
  181. * - ESP_ERR_INVALID_ARG: Function is not valid
  182. * - ESP_ERR_TIMEOUT: There's no transaction done before timeout
  183. * - ESP_ERR_INVALID_STATE: Function called in invalid state. This API should be called under append mode.
  184. */
  185. esp_err_t spi_slave_hd_get_append_trans_res(spi_host_device_t host_id, spi_slave_chan_t chan, spi_slave_hd_data_t **out_trans, TickType_t timeout);
  186. #ifdef __cplusplus
  187. }
  188. #endif