spi_slave_hd_hal.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. // Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. /*******************************************************************************
  15. * NOTICE
  16. * The hal is not public api, don't use in application code.
  17. * See readme.md in hal/include/hal/readme.md
  18. ******************************************************************************/
  19. /*
  20. * The HAL layer for SPI Slave HD mode.
  21. *
  22. * Usage (segment mode):
  23. * - Firstly, initialize the slave with `spi_slave_hd_hal_init`
  24. *
  25. * - Event handling:
  26. * - (Optional) Call ``spi_slave_hd_hal_enable_event_intr`` to enable the used interrupts
  27. * - (Basic) Call ``spi_slave_hd_hal_check_clear_event`` to check whether an event happen, and also
  28. * clear its interrupt. For events: SPI_EV_BUF_TX, SPI_EV_BUF_RX, SPI_EV_BUF_RX, SPI_EV_CMD9,
  29. * SPI_EV_CMDA.
  30. * - (Advanced) Call ``spi_slave_hd_hal_check_disable_event`` to disable the interrupt of an event,
  31. * so that the task can call ``spi_slave_hd_hal_invoke_event_intr`` later to manually invoke the
  32. * ISR. For SPI_EV_SEND, SPI_EV_RECV.
  33. *
  34. * - TXDMA:
  35. * - To send data through DMA, call `spi_slave_hd_hal_txdma`
  36. * - When the operation is done, SPI_EV_SEND will be triggered.
  37. *
  38. * - RXDMA:
  39. * - To receive data through DMA, call `spi_slave_hd_hal_rxdma`
  40. * - When the operation is done, SPI_EV_RECV will be triggered.
  41. * - Call ``spi_slave_hd_hal_rxdma_seg_get_len`` to get the received length
  42. *
  43. * - Shared buffer:
  44. * - Call ``spi_slave_hd_hal_write_buffer`` to write the shared register buffer. When the buffer is
  45. * read by the master (regardless of the read address), SPI_EV_BUF_TX will be triggered
  46. * - Call ``spi_slave_hd_hal_read_buffer`` to read the shared register buffer. When the buffer is
  47. * written by the master (regardless of the written address), SPI_EV_BUF_RX will be triggered.
  48. */
  49. #pragma once
  50. #include <esp_types.h>
  51. #include "esp_err.h"
  52. #include "hal/spi_ll.h"
  53. #include "hal/spi_types.h"
  54. /**
  55. * @brief Type of dma descriptor with appended members
  56. * this structure inherits DMA descriptor, with a pointer to the transaction descriptor passed from users.
  57. */
  58. typedef struct {
  59. lldesc_t desc; ///< DMA descriptor
  60. void *arg; ///< This points to the transaction descriptor user passed in
  61. } spi_slave_hd_hal_desc_append_t;
  62. /// Configuration of the HAL
  63. typedef struct {
  64. uint32_t host_id; ///< Host ID of the spi peripheral
  65. spi_dma_dev_t *dma_in; ///< Input DMA(DMA -> RAM) peripheral register address
  66. spi_dma_dev_t *dma_out; ///< Output DMA(RAM -> DMA) peripheral register address
  67. bool dma_enabled; ///< DMA enabled or not
  68. uint32_t tx_dma_chan; ///< TX DMA channel used.
  69. uint32_t rx_dma_chan; ///< RX DMA channel used.
  70. bool append_mode; ///< True for DMA append mode, false for segment mode
  71. uint32_t spics_io_num; ///< CS GPIO pin for this device
  72. uint8_t mode; ///< SPI mode (0-3)
  73. uint32_t command_bits; ///< command field bits, multiples of 8 and at least 8.
  74. uint32_t address_bits; ///< address field bits, multiples of 8 and at least 8.
  75. uint32_t dummy_bits; ///< dummy field bits, multiples of 8 and at least 8.
  76. struct {
  77. uint32_t tx_lsbfirst : 1; ///< Whether TX data should be sent with LSB first.
  78. uint32_t rx_lsbfirst : 1; ///< Whether RX data should be read with LSB first.
  79. };
  80. } spi_slave_hd_hal_config_t;
  81. /// Context of the HAL, initialized by :cpp:func:`spi_slave_hd_hal_init`.
  82. typedef struct {
  83. /* These two need to be malloced by the driver first */
  84. spi_slave_hd_hal_desc_append_t *dmadesc_tx; ///< Head of the TX DMA descriptors.
  85. spi_slave_hd_hal_desc_append_t *dmadesc_rx; ///< Head of the RX DMA descriptors.
  86. /* address of the hardware */
  87. spi_dev_t *dev; ///< Beginning address of the peripheral registers.
  88. spi_dma_dev_t *dma_in; ///< Address of the DMA peripheral registers which stores the data received from a peripheral into RAM.
  89. spi_dma_dev_t *dma_out; ///< Address of the DMA peripheral registers which transmits the data from RAM to a peripheral.
  90. bool dma_enabled; ///< DMA enabled or not
  91. uint32_t tx_dma_chan; ///< TX DMA channel used.
  92. uint32_t rx_dma_chan; ///< RX DMA channel used.
  93. bool append_mode; ///< True for DMA append mode, false for segment mode
  94. uint32_t dma_desc_num; ///< Number of the available DMA descriptors. Calculated from ``bus_max_transfer_size``.
  95. spi_slave_hd_hal_desc_append_t *tx_cur_desc; ///< Current TX DMA descriptor that could be linked (set up).
  96. spi_slave_hd_hal_desc_append_t *tx_dma_head; ///< Head of the linked TX DMA descriptors which are not used by hardware
  97. spi_slave_hd_hal_desc_append_t *tx_dma_tail; ///< Tail of the linked TX DMA descriptors which are not used by hardware
  98. spi_slave_hd_hal_desc_append_t tx_dummy_head; ///< Dummy descriptor for ``tx_dma_head`` to start
  99. uint32_t tx_used_desc_cnt; ///< Number of the TX descriptors that have been setup
  100. uint32_t tx_recycled_desc_cnt; ///< Number of the TX descriptors that could be recycled
  101. spi_slave_hd_hal_desc_append_t *rx_cur_desc; ///< Current RX DMA descriptor that could be linked (set up).
  102. spi_slave_hd_hal_desc_append_t *rx_dma_head; ///< Head of the linked RX DMA descriptors which are not used by hardware
  103. spi_slave_hd_hal_desc_append_t *rx_dma_tail; ///< Tail of the linked RX DMA descriptors which are not used by hardware
  104. spi_slave_hd_hal_desc_append_t rx_dummy_head; ///< Dummy descriptor for ``rx_dma_head`` to start
  105. uint32_t rx_used_desc_cnt; ///< Number of the RX descriptors that have been setup
  106. uint32_t rx_recycled_desc_cnt; ///< Number of the RX descriptors that could be recycled
  107. /* Internal status used by the HAL implementation, initialized as 0. */
  108. uint32_t intr_not_triggered;
  109. bool tx_dma_started;
  110. bool rx_dma_started;
  111. } spi_slave_hd_hal_context_t;
  112. /**
  113. * @brief Initialize the hardware and part of the context
  114. *
  115. * @param hal Context of the HAL layer
  116. * @param hal_config Configuration of the HAL
  117. */
  118. void spi_slave_hd_hal_init(spi_slave_hd_hal_context_t *hal, const spi_slave_hd_hal_config_t *hal_config);
  119. /**
  120. * @brief Get the size of one DMA descriptor
  121. *
  122. * @param hal Context of the HAL layer
  123. * @param bus_size SPI bus maximum transfer size, in bytes.
  124. * @return Total size needed for all the DMA descriptors
  125. */
  126. uint32_t spi_slave_hd_hal_get_total_desc_size(spi_slave_hd_hal_context_t *hal, uint32_t bus_size);
  127. /**
  128. * @brief Get the actual bus size
  129. *
  130. * @param hal Context of the HAL layer
  131. * @return Actual bus transaction size
  132. */
  133. uint32_t spi_salve_hd_hal_get_max_bus_size(spi_slave_hd_hal_context_t *hal);
  134. /**
  135. * @brief Check and clear signal of one event
  136. *
  137. * @param hal Context of the HAL layer
  138. * @param ev Event to check
  139. * @return True if event triggered, otherwise false
  140. */
  141. bool spi_slave_hd_hal_check_clear_event(spi_slave_hd_hal_context_t* hal, spi_event_t ev);
  142. /**
  143. * @brief Check and clear the interrupt of one event.
  144. *
  145. * @note The event source will be kept, so that the interrupt can be invoked by
  146. * :cpp:func:`spi_slave_hd_hal_invoke_event_intr`. If event not triggered, its interrupt source
  147. * will not be disabled either.
  148. *
  149. * @param hal Context of the HAL layer
  150. * @param ev Event to check and disable
  151. * @return True if event triggered, otherwise false
  152. */
  153. bool spi_slave_hd_hal_check_disable_event(spi_slave_hd_hal_context_t* hal, spi_event_t ev);
  154. /**
  155. * @brief Enable to invole the ISR of corresponding event.
  156. *
  157. * @note The function, compared with :cpp:func:`spi_slave_hd_hal_enable_event_intr`, contains a
  158. * workaround to force trigger the interrupt, even if the interrupt source cannot be initialized
  159. * correctly.
  160. *
  161. * @param hal Context of the HAL layer
  162. * @param ev Event (reason) to invoke the ISR
  163. */
  164. void spi_slave_hd_hal_invoke_event_intr(spi_slave_hd_hal_context_t* hal, spi_event_t ev);
  165. /**
  166. * @brief Enable the interrupt source of corresponding event.
  167. *
  168. * @param hal Context of the HAL layer
  169. * @param ev Event whose corresponding interrupt source should be enabled.
  170. */
  171. void spi_slave_hd_hal_enable_event_intr(spi_slave_hd_hal_context_t* hal, spi_event_t ev);
  172. ////////////////////////////////////////////////////////////////////////////////
  173. // RX DMA
  174. ////////////////////////////////////////////////////////////////////////////////
  175. /**
  176. * @brief Start the RX DMA operation to the specified buffer.
  177. *
  178. * @param hal Context of the HAL layer
  179. * @param[out] out_buf Buffer to receive the data
  180. * @param len Maximul length to receive
  181. */
  182. void spi_slave_hd_hal_rxdma(spi_slave_hd_hal_context_t *hal, uint8_t *out_buf, size_t len);
  183. /**
  184. * @brief Get the length of total received data
  185. *
  186. * @param hal Context of the HAL layer
  187. * @return The received length
  188. */
  189. int spi_slave_hd_hal_rxdma_seg_get_len(spi_slave_hd_hal_context_t *hal);
  190. ////////////////////////////////////////////////////////////////////////////////
  191. // TX DMA
  192. ////////////////////////////////////////////////////////////////////////////////
  193. /**
  194. * @brief Start the TX DMA operation with the specified buffer
  195. *
  196. * @param hal Context of the HAL layer
  197. * @param data Buffer of data to send
  198. * @param len Size of the buffer, also the maximum length to send
  199. */
  200. void spi_slave_hd_hal_txdma(spi_slave_hd_hal_context_t *hal, uint8_t *data, size_t len);
  201. ////////////////////////////////////////////////////////////////////////////////
  202. // Shared buffer
  203. ////////////////////////////////////////////////////////////////////////////////
  204. /**
  205. * @brief Read from the shared register buffer
  206. *
  207. * @param hal Context of the HAL layer
  208. * @param addr Address of the shared regsiter to read
  209. * @param out_data Buffer to store the read data
  210. * @param len Length to read from the shared buffer
  211. */
  212. void spi_slave_hd_hal_read_buffer(spi_slave_hd_hal_context_t *hal, int addr, uint8_t *out_data, size_t len);
  213. /**
  214. * @brief Write the shared register buffer
  215. *
  216. * @param hal Context of the HAL layer
  217. * @param addr Address of the shared register to write
  218. * @param data Buffer of the data to write
  219. * @param len Length to write into the shared buffer
  220. */
  221. void spi_slave_hd_hal_write_buffer(spi_slave_hd_hal_context_t *hal, int addr, uint8_t *data, size_t len);
  222. /**
  223. * @brief Get the length of previous transaction.
  224. *
  225. * @param hal Context of the HAL layer
  226. * @return The length of previous transaction
  227. */
  228. int spi_slave_hd_hal_get_rxlen(spi_slave_hd_hal_context_t *hal);
  229. /**
  230. * @brief Get the address of last transaction
  231. *
  232. * @param hal Context of the HAL layer
  233. * @return The address of last transaction
  234. */
  235. int spi_slave_hd_hal_get_last_addr(spi_slave_hd_hal_context_t *hal);
  236. #if CONFIG_IDF_TARGET_ESP32S2
  237. //Append mode is only supported on ESP32S2 now
  238. ////////////////////////////////////////////////////////////////////////////////
  239. // Append Mode
  240. ////////////////////////////////////////////////////////////////////////////////
  241. /**
  242. * @brief Return the finished TX transaction
  243. *
  244. * @note This API is based on this assumption: the hardware behaviour of current transaction completion is only modified by the its own caller layer.
  245. * This means if some other code changed the hardware behaviour (e.g. clear intr raw bit), or the caller call this API without noticing the HW behaviour,
  246. * this API will go wrong.
  247. *
  248. * @param hal Context of the HAL layer
  249. * @param out_trans Pointer to the caller-defined transaction
  250. * @return 1: Transaction is finished; 0: Transaction is not finished
  251. */
  252. bool spi_slave_hd_hal_get_tx_finished_trans(spi_slave_hd_hal_context_t *hal, void **out_trans);
  253. /**
  254. * @brief Return the finished RX transaction
  255. *
  256. * @note This API is based on this assumption: the hardware behaviour of current transaction completion is only modified by the its own caller layer.
  257. * This means if some other code changed the hardware behaviour (e.g. clear intr raw bit), or the caller call this API without noticing the HW behaviour,
  258. * this API will go wrong.
  259. *
  260. * @param hal Context of the HAL layer
  261. * @param out_trans Pointer to the caller-defined transaction
  262. * @param out_len Actual number of bytes of received data
  263. * @return 1: Transaction is finished; 0: Transaction is not finished
  264. */
  265. bool spi_slave_hd_hal_get_rx_finished_trans(spi_slave_hd_hal_context_t *hal, void **out_trans, size_t *out_len);
  266. /**
  267. * @brief Load the TX DMA descriptors without stopping the DMA
  268. *
  269. * @param hal Context of the HAL layer
  270. * @param data Buffer of the transaction data
  271. * @param len Length of the data
  272. * @param arg Pointer used by the caller to indicate the tranaction. Will be returned by ``spi_slave_hd_hal_get_tx_finished_trans`` when transaction is finished
  273. * @return
  274. * - ESP_OK: on success
  275. * - ESP_ERR_INVALID_STATE: Function called in invalid state.
  276. */
  277. esp_err_t spi_slave_hd_hal_txdma_append(spi_slave_hd_hal_context_t *hal, uint8_t *data, size_t len, void *arg);
  278. /**
  279. * @brief Load the RX DMA descriptors without stopping the DMA
  280. *
  281. * @param hal Context of the HAL layer
  282. * @param data Buffer of the transaction data
  283. * @param len Length of the data
  284. * @param arg Pointer used by the caller to indicate the tranaction. Will be returned by ``spi_slave_hd_hal_get_rx_finished_trans`` when transaction is finished
  285. * @return
  286. * - ESP_OK: on success
  287. * - ESP_ERR_INVALID_STATE: Function called in invalid state.
  288. */
  289. esp_err_t spi_slave_hd_hal_rxdma_append(spi_slave_hd_hal_context_t *hal, uint8_t *data, size_t len, void *arg);
  290. #endif //#if CONFIG_IDF_TARGET_ESP32S2