gdma.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. // Copyright 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. // DO NOT USE THESE APIS IN ANY APPLICATIONS
  15. // GDMA driver is not public for end users, but for ESP-IDF developpers.
  16. #pragma once
  17. #include <stdbool.h>
  18. #include "soc/gdma_channel.h"
  19. #include "esp_err.h"
  20. #ifdef __cplusplus
  21. extern "C" {
  22. #endif
  23. /**
  24. * @brief Type of GDMA channel handle
  25. *
  26. */
  27. typedef struct gdma_channel_t *gdma_channel_handle_t;
  28. /**
  29. * @brief Enumeration of peripherals which have the DMA capability
  30. * @note Some peripheral might not be available on certain chip, please refer to `soc_caps.h` for detail.
  31. *
  32. */
  33. typedef enum {
  34. GDMA_TRIG_PERIPH_M2M, /*!< GDMA trigger peripheral: M2M */
  35. GDMA_TRIG_PERIPH_UART, /*!< GDMA trigger peripheral: UART */
  36. GDMA_TRIG_PERIPH_SPI, /*!< GDMA trigger peripheral: SPI */
  37. GDMA_TRIG_PERIPH_I2S, /*!< GDMA trigger peripheral: I2S */
  38. GDMA_TRIG_PERIPH_AES, /*!< GDMA trigger peripheral: AES */
  39. GDMA_TRIG_PERIPH_SHA, /*!< GDMA trigger peripheral: SHA */
  40. GDMA_TRIG_PERIPH_ADC, /*!< GDMA trigger peripheral: ADC */
  41. GDMA_TRIG_PERIPH_DAC, /*!< GDMA trigger peripheral: DAC */
  42. GDMA_TRIG_PERIPH_LCD, /*!< GDMA trigger peripheral: LCD */
  43. GDMA_TRIG_PERIPH_CAM /*!< GDMA trigger peripheral: CAM */
  44. } gdma_trigger_peripheral_t;
  45. /**
  46. * @brief Enumeration of GDMA channel direction
  47. *
  48. */
  49. typedef enum {
  50. GDMA_CHANNEL_DIRECTION_TX, /*!< GDMA channel direction: TX */
  51. GDMA_CHANNEL_DIRECTION_RX, /*!< GDMA channel direction: RX */
  52. } gdma_channel_direction_t;
  53. /**
  54. * @brief Collection of configuration items that used for allocating GDMA channel
  55. *
  56. */
  57. typedef struct {
  58. gdma_channel_handle_t sibling_chan; /*!< DMA sibling channel handle (NULL means having sibling is not necessary) */
  59. gdma_channel_direction_t direction; /*!< DMA channel direction */
  60. struct {
  61. int reserve_sibling: 1; /*!< If set, DMA channel allocator would prefer to allocate new channel in a new pair, and reserve sibling channel for future use */
  62. } flags;
  63. } gdma_channel_alloc_config_t;
  64. /**
  65. * @brief Type of GDMA event data
  66. *
  67. */
  68. typedef struct {
  69. union {
  70. intptr_t rx_eof_desc_addr; /*!< EOF descriptor address of RX channel */
  71. intptr_t tx_eof_desc_addr; /*!< EOF descriptor address of TX channel */
  72. };
  73. } gdma_event_data_t;
  74. /**
  75. * @brief Type of GDMA event callback
  76. * @param dma_chan GDMA channel handle, created from `gdma_new_channel`
  77. * @param event_data GDMA event data
  78. * @param user_data User registered data from `gdma_register_tx_event_callbacks` or `gdma_register_rx_event_callbacks`
  79. *
  80. */
  81. typedef bool (*gdma_event_callback_t)(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data);
  82. /**
  83. * @brief Group of supported GDMA TX callbacks
  84. * @note The callbacks are all running under ISR environment
  85. *
  86. */
  87. typedef struct {
  88. gdma_event_callback_t on_trans_eof; /*!< Invoked when TX engine meets EOF descriptor */
  89. } gdma_tx_event_callbacks_t;
  90. /**
  91. * @brief Group of supported GDMA RX callbacks
  92. * @note The callbacks are all running under ISR environment
  93. *
  94. */
  95. typedef struct {
  96. gdma_event_callback_t on_recv_eof; /*!< Invoked when RX engine meets EOF descriptor */
  97. } gdma_rx_event_callbacks_t;
  98. /**
  99. * @brief Type of GDMA engine trigger
  100. * @note It's recommended to initialize this structure with `GDMA_MAKE_TRIGGER`.
  101. *
  102. */
  103. typedef struct {
  104. gdma_trigger_peripheral_t periph; /*!< Target peripheral which will trigger DMA operations */
  105. int instance_id; /*!< Peripheral instance ID. Supported IDs are listed in `soc/gdma_channel.h`, e.g. SOC_GDMA_TRIG_PERIPH_UART0 */
  106. } gdma_trigger_t;
  107. /**
  108. * @brief Helper macro to initialize GDMA trigger
  109. * @note value of `peri` must be selected from `gdma_trigger_peripheral_t` enum.
  110. * e.g. GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_UART,0)
  111. *
  112. */
  113. #define GDMA_MAKE_TRIGGER(peri, id) \
  114. (gdma_trigger_t) { .periph = peri, .instance_id = SOC_##peri##id }
  115. /**
  116. * @brief A collection of strategy item that each GDMA channel could apply
  117. *
  118. */
  119. typedef struct {
  120. bool owner_check; /*!< If set / clear, DMA channel enables / disables checking owner validity */
  121. bool auto_update_desc; /*!< If set / clear, DMA channel enables / disables hardware to update descriptor automatically (TX channel only) */
  122. } gdma_strategy_config_t;
  123. /**
  124. * @brief Create GDMA channel
  125. * @note This API won't install interrupt service for the allocated channel.
  126. * If interrupt service is needed, user has to register GDMA event callback by `gdma_register_tx_event_callbacks` or `gdma_register_rx_event_callbacks`.
  127. *
  128. * @param[in] config Pointer to a collection of configurations for allocating GDMA channel
  129. * @param[out] ret_chan Returnned channel handle
  130. * @return
  131. * - ESP_OK: Create DMA channel successfully
  132. * - ESP_ERR_INVALID_ARG: Create DMA channel failed because of invalid argument
  133. * - ESP_ERR_NO_MEM: Create DMA channel failed because out of memory
  134. * - ESP_FAIL: Create DMA channel failed because of other error
  135. */
  136. esp_err_t gdma_new_channel(const gdma_channel_alloc_config_t *config, gdma_channel_handle_t *ret_chan);
  137. /**
  138. * @brief Connect GDMA channel to trigger peripheral
  139. *
  140. * @note Suggest to use helper macro `GDMA_MAKE_TRIGGER` to construct parameter `trig_periph`. e.g. GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_SHA,0)
  141. *
  142. * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel`
  143. * @param[in] trig_periph GDMA trigger peripheral
  144. * @return
  145. * - ESP_OK: Connect GDMA channel successfully
  146. * - ESP_ERR_INVALID_ARG: Connect GDMA channel failed because of invalid argument
  147. * - ESP_ERR_INVALID_STATE: Connect GDMA channel failed because DMA channel is working with another peripheral
  148. * - ESP_FAIL: Connect GDMA channel failed because of other error
  149. */
  150. esp_err_t gdma_connect(gdma_channel_handle_t dma_chan, gdma_trigger_t trig_periph);
  151. /**
  152. * @brief Disconnect GMA channel from peripheral
  153. *
  154. * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel`
  155. * @return
  156. * - ESP_OK: Disconnect GDMA channel successfully
  157. * - ESP_ERR_INVALID_ARG: Disconnect GDMA channel failed because of invalid argument
  158. * - ESP_ERR_INVALID_STATE: Disconnect GDMA channel failed because DMA channel is not connected to any peripheral
  159. * - ESP_FAIL: Disconnect DMA channel failed because of other error
  160. */
  161. esp_err_t gdma_disconnect(gdma_channel_handle_t dma_chan);
  162. /**
  163. * @brief Apply channel strategy for GDMA channel
  164. *
  165. * @param dma_chan GDMA channel handle, allocated by `gdma_new_channel`
  166. * @param config Configuration of GDMA channel strategy
  167. * - ESP_OK: Apply channel strategy successfully
  168. * - ESP_ERR_INVALID_ARG: Apply channel strategy failed because of invalid argument
  169. * - ESP_FAIL: Apply channel strategy failed because of other error
  170. */
  171. esp_err_t gdma_apply_strategy(gdma_channel_handle_t dma_chan, const gdma_strategy_config_t *config);
  172. /**
  173. * @brief Delete GDMA channel
  174. * @note If you call `gdma_new_channel` several times for a same peripheral, make sure you call this API the same times.
  175. *
  176. * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel`
  177. * @return
  178. * - ESP_OK: Delete GDMA channel successfully
  179. * - ESP_ERR_INVALID_ARG: Delete GDMA channel failed because of invalid argument
  180. * - ESP_FAIL: Delete GDMA channel failed because of other error
  181. */
  182. esp_err_t gdma_del_channel(gdma_channel_handle_t dma_chan);
  183. /**
  184. * @brief Get the channel ID
  185. *
  186. * @note This API breaks the encapsulation of GDMA Channel Object.
  187. * With the returned channel ID, you can even bypass all other GDMA driver API and access Low Level API directly.
  188. *
  189. * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel`
  190. * @param[out] channel_id Returned channel ID
  191. * @return
  192. * - ESP_OK: Get GDMA channel ID successfully
  193. * - ESP_ERR_INVALID_ARG: Get GDMA channel ID failed because of invalid argument
  194. * - ESP_FAIL: Get GDMA channel ID failed because of other error
  195. */
  196. esp_err_t gdma_get_channel_id(gdma_channel_handle_t dma_chan, int *channel_id);
  197. /**
  198. * @brief Set GDMA event callbacks for TX channel
  199. * @note This API will install GDMA interrupt service for the channel internally
  200. *
  201. * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel`
  202. * @param[in] cbs Group of callback functions
  203. * @param[in] user_data User data, which will be passed to callback functions directly
  204. * @return
  205. * - ESP_OK: Set event callbacks successfully
  206. * - ESP_ERR_INVALID_ARG: Set event callbacks failed because of invalid argument
  207. * - ESP_FAIL: Set event callbacks failed because of other error
  208. */
  209. esp_err_t gdma_register_tx_event_callbacks(gdma_channel_handle_t dma_chan, gdma_tx_event_callbacks_t *cbs, void *user_data);
  210. /**
  211. * @brief Set GDMA event callbacks for RX channel
  212. * @note This API will install GDMA interrupt service for the channel internally
  213. *
  214. * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel`
  215. * @param[in] cbs Group of callback functions
  216. * @param[in] user_data User data, which will be passed to callback functions directly
  217. * @return
  218. * - ESP_OK: Set event callbacks successfully
  219. * - ESP_ERR_INVALID_ARG: Set event callbacks failed because of invalid argument
  220. * - ESP_FAIL: Set event callbacks failed because of other error
  221. */
  222. esp_err_t gdma_register_rx_event_callbacks(gdma_channel_handle_t dma_chan, gdma_rx_event_callbacks_t *cbs, void *user_data);
  223. /**
  224. * @brief Set DMA descriptor address and start engine
  225. *
  226. * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel`
  227. * @param[in] desc_base_addr Base address of descriptors (usually the descriptors are chained into a link or ring)
  228. * @return
  229. * - ESP_OK: Start DMA engine successfully
  230. * - ESP_ERR_INVALID_ARG: Start DMA engine failed because of invalid argument
  231. * - ESP_FAIL: Start DMA engine failed because of other error
  232. */
  233. esp_err_t gdma_start(gdma_channel_handle_t dma_chan, intptr_t desc_base_addr);
  234. /**
  235. * @brief Stop DMA engine
  236. *
  237. * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel`
  238. * @return
  239. * - ESP_OK: Stop DMA engine successfully
  240. * - ESP_ERR_INVALID_ARG: Stop DMA engine failed because of invalid argument
  241. * - ESP_FAIL: Stop DMA engine failed because of other error
  242. */
  243. esp_err_t gdma_stop(gdma_channel_handle_t dma_chan);
  244. /**
  245. * @brief Make the appended descriptors be aware to the DMA engine
  246. * @note This API could also resume a paused DMA engine, make sure new descriptors have been appended to the descriptor chain before calling it.
  247. *
  248. * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel`
  249. * @return
  250. * - ESP_OK: Send append command to DMA engine successfully
  251. * - ESP_ERR_INVALID_ARG: Send append command to DMA engine failed because of invalid argument
  252. * - ESP_FAIL: Send append command to DMA engine failed because of other error
  253. */
  254. esp_err_t gdma_append(gdma_channel_handle_t dma_chan);
  255. #ifdef __cplusplus
  256. }
  257. #endif