gdma.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. /*
  2. * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. // DO NOT USE THESE APIS IN ANY APPLICATIONS
  7. // GDMA driver is not public for end users, but for ESP-IDF developers.
  8. #pragma once
  9. #include <stdbool.h>
  10. #include "esp_etm.h"
  11. #include "soc/gdma_channel.h"
  12. #include "hal/gdma_types.h"
  13. #include "esp_err.h"
  14. #ifdef __cplusplus
  15. extern "C" {
  16. #endif
  17. /**
  18. * @brief Type of GDMA channel handle
  19. *
  20. */
  21. typedef struct gdma_channel_t *gdma_channel_handle_t;
  22. /**
  23. * @brief Collection of configuration items that used for allocating GDMA channel
  24. *
  25. */
  26. typedef struct {
  27. gdma_channel_handle_t sibling_chan; /*!< DMA sibling channel handle (NULL means having sibling is not necessary) */
  28. gdma_channel_direction_t direction; /*!< DMA channel direction */
  29. struct {
  30. 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 */
  31. } flags;
  32. } gdma_channel_alloc_config_t;
  33. /**
  34. * @brief GDMA transfer ability
  35. *
  36. * @note The alignment set in this structure is **not** a guarantee that gdma driver will take care of the nonalignment cases.
  37. * Actually the GDMA driver has no knowledge about the DMA buffer (address and size) used by upper layer.
  38. * So it's the responsibility of the **upper layer** to take care of the buffer address and size.
  39. *
  40. */
  41. typedef struct {
  42. size_t sram_trans_align; /*!< DMA transfer alignment for memory in SRAM, in bytes. The driver enables/disables burst mode based on this value. 0 means no alignment is required */
  43. size_t psram_trans_align; /*!< DMA transfer alignment for memory in PSRAM, in bytes. The driver sets proper burst block size based on the alignment value. 0 means no alignment is required */
  44. } gdma_transfer_ability_t;
  45. /**
  46. * @brief Type of GDMA event data
  47. */
  48. typedef struct {
  49. union {
  50. intptr_t rx_eof_desc_addr; /*!< EOF descriptor address of RX channel */
  51. intptr_t tx_eof_desc_addr; /*!< EOF descriptor address of TX channel */
  52. };
  53. struct {
  54. uint32_t abnormal_eof: 1; /*!< 0: normal/success EOF;
  55. * 1: abnormal/error EOF,
  56. * it doesn't mean GDMA goes into an error condition,
  57. * but the other peripheral goes into an abnormal state.
  58. * For GDMA, it's still a valid EOF
  59. */
  60. } flags;
  61. } gdma_event_data_t;
  62. /**
  63. * @brief Type of GDMA event callback
  64. * @param dma_chan GDMA channel handle, created from `gdma_new_channel`
  65. * @param event_data GDMA event data. Different event share the same data structure, but the caller may only use a few or none of the data members.
  66. * @param user_data User registered data from `gdma_register_tx_event_callbacks` or `gdma_register_rx_event_callbacks`
  67. *
  68. * @return Whether a task switch is needed after the callback function returns,
  69. * this is usually due to the callback wakes up some high priority task.
  70. */
  71. typedef bool (*gdma_event_callback_t)(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data);
  72. /**
  73. * @brief Group of supported GDMA TX callbacks
  74. * @note The callbacks are all running under ISR environment
  75. */
  76. typedef struct {
  77. gdma_event_callback_t on_trans_eof; /*!< Invoked when TX engine meets EOF descriptor */
  78. gdma_event_callback_t on_descr_err; /*!< Invoked when DMA encounters a descriptor error */
  79. } gdma_tx_event_callbacks_t;
  80. /**
  81. * @brief Group of supported GDMA RX callbacks
  82. * @note The callbacks are all running under ISR environment
  83. */
  84. typedef struct {
  85. gdma_event_callback_t on_recv_eof; /*!< Invoked when RX engine meets EOF descriptor */
  86. gdma_event_callback_t on_descr_err; /*!< Invoked when DMA encounters a descriptor error */
  87. gdma_event_callback_t on_recv_done; /*!< Invoked when finished to receive one RX descriptor */
  88. } gdma_rx_event_callbacks_t;
  89. /**
  90. * @brief Type of GDMA engine trigger
  91. * @note It's recommended to initialize this structure with `GDMA_MAKE_TRIGGER`.
  92. *
  93. */
  94. typedef struct {
  95. gdma_trigger_peripheral_t periph; /*!< Target peripheral which will trigger DMA operations */
  96. int instance_id; /*!< Peripheral instance ID. Supported IDs are listed in `soc/gdma_channel.h`, e.g. SOC_GDMA_TRIG_PERIPH_UHCI0 */
  97. int bus_id; /*!< Which system bus should the DMA attached to */
  98. } gdma_trigger_t;
  99. /**
  100. * @brief Helper macro to initialize GDMA trigger
  101. * @note value of `peri` must be selected from `gdma_trigger_peripheral_t` enum.
  102. * e.g. GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_I2S,0)
  103. *
  104. */
  105. #define GDMA_MAKE_TRIGGER(peri, id) \
  106. (gdma_trigger_t) { .periph = peri, .instance_id = SOC_##peri##id, .bus_id = SOC_##peri##id##_BUS }
  107. /**
  108. * @brief A collection of strategy item that each GDMA channel could apply
  109. *
  110. */
  111. typedef struct {
  112. bool owner_check; /*!< If set / clear, DMA channel enables / disables checking owner validity */
  113. bool auto_update_desc; /*!< If set / clear, DMA channel enables / disables hardware to update descriptor automatically (TX channel only) */
  114. } gdma_strategy_config_t;
  115. /** @cond */
  116. /**
  117. * @brief Create GDMA channel (only create AHB GDMA channel)
  118. * @note This API is going to be deprecated, please use `gdma_new_ahb_channel` or `gdma_new_axi_channel` instead.
  119. *
  120. * @param[in] config Pointer to a collection of configurations for allocating GDMA channel
  121. * @param[out] ret_chan Returned channel handle
  122. * @return
  123. * - ESP_OK: Create DMA channel successfully
  124. * - ESP_ERR_INVALID_ARG: Create DMA channel failed because of invalid argument
  125. * - ESP_ERR_NO_MEM: Create DMA channel failed because out of memory
  126. * - ESP_FAIL: Create DMA channel failed because of other error
  127. */
  128. esp_err_t gdma_new_channel(const gdma_channel_alloc_config_t *config, gdma_channel_handle_t *ret_chan);
  129. /** @endcond */
  130. /**
  131. * @brief Create AHB-GDMA channel
  132. * @note This API won't install interrupt service for the allocated channel.
  133. * If interrupt service is needed, user has to register GDMA event callback by `gdma_register_tx_event_callbacks` or `gdma_register_rx_event_callbacks`.
  134. *
  135. * @param[in] config Pointer to a collection of configurations for allocating GDMA channel
  136. * @param[out] ret_chan Returned channel handle
  137. * @return
  138. * - ESP_OK: Create DMA channel successfully
  139. * - ESP_ERR_INVALID_ARG: Create DMA channel failed because of invalid argument
  140. * - ESP_ERR_NO_MEM: Create DMA channel failed because out of memory
  141. * - ESP_FAIL: Create DMA channel failed because of other error
  142. */
  143. esp_err_t gdma_new_ahb_channel(const gdma_channel_alloc_config_t *config, gdma_channel_handle_t *ret_chan);
  144. /**
  145. * @brief Create AXI-GDMA channel
  146. * @note This API won't install interrupt service for the allocated channel.
  147. * If interrupt service is needed, user has to register GDMA event callback by `gdma_register_tx_event_callbacks` or `gdma_register_rx_event_callbacks`.
  148. *
  149. * @param[in] config Pointer to a collection of configurations for allocating GDMA channel
  150. * @param[out] ret_chan Returned channel handle
  151. * @return
  152. * - ESP_OK: Create DMA channel successfully
  153. * - ESP_ERR_INVALID_ARG: Create DMA channel failed because of invalid argument
  154. * - ESP_ERR_NO_MEM: Create DMA channel failed because out of memory
  155. * - ESP_FAIL: Create DMA channel failed because of other error
  156. */
  157. esp_err_t gdma_new_axi_channel(const gdma_channel_alloc_config_t *config, gdma_channel_handle_t *ret_chan);
  158. /**
  159. * @brief Connect GDMA channel to trigger peripheral
  160. *
  161. * @note Suggest to use helper macro `GDMA_MAKE_TRIGGER` to construct parameter `trig_periph`. e.g. GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_SHA,0)
  162. * @note Connecting to a peripheral will also reset the DMA FIFO and FSM automatically
  163. *
  164. * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel`
  165. * @param[in] trig_periph GDMA trigger peripheral
  166. * @return
  167. * - ESP_OK: Connect GDMA channel successfully
  168. * - ESP_ERR_INVALID_ARG: Connect GDMA channel failed because of invalid argument
  169. * - ESP_ERR_INVALID_STATE: Connect GDMA channel failed because DMA channel is working with another peripheral
  170. * - ESP_FAIL: Connect GDMA channel failed because of other error
  171. */
  172. esp_err_t gdma_connect(gdma_channel_handle_t dma_chan, gdma_trigger_t trig_periph);
  173. /**
  174. * @brief Disconnect GMA channel from peripheral
  175. *
  176. * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel`
  177. * @return
  178. * - ESP_OK: Disconnect GDMA channel successfully
  179. * - ESP_ERR_INVALID_ARG: Disconnect GDMA channel failed because of invalid argument
  180. * - ESP_ERR_INVALID_STATE: Disconnect GDMA channel failed because DMA channel is not connected to any peripheral
  181. * - ESP_FAIL: Disconnect DMA channel failed because of other error
  182. */
  183. esp_err_t gdma_disconnect(gdma_channel_handle_t dma_chan);
  184. /**
  185. * @brief Set DMA channel transfer ability
  186. *
  187. * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel`
  188. * @param[in] ability Transfer ability, e.g. alignment
  189. * @return
  190. * - ESP_OK: Set DMA channel transfer ability successfully
  191. * - ESP_ERR_INVALID_ARG: Set DMA channel transfer ability failed because of invalid argument
  192. * - ESP_FAIL: Set DMA channel transfer ability failed because of other error
  193. */
  194. esp_err_t gdma_set_transfer_ability(gdma_channel_handle_t dma_chan, const gdma_transfer_ability_t *ability);
  195. /**
  196. * @brief Apply channel strategy for GDMA channel
  197. *
  198. * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel`
  199. * @param[in] config Configuration of GDMA channel strategy
  200. * - ESP_OK: Apply channel strategy successfully
  201. * - ESP_ERR_INVALID_ARG: Apply channel strategy failed because of invalid argument
  202. * - ESP_FAIL: Apply channel strategy failed because of other error
  203. */
  204. esp_err_t gdma_apply_strategy(gdma_channel_handle_t dma_chan, const gdma_strategy_config_t *config);
  205. /**
  206. * @brief Set GDMA channel priority
  207. *
  208. * @note By default, all GDMA channels are with the same priority: 0. Channels with the same priority are served in round-robin manner.
  209. *
  210. * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel`
  211. * @param[in] priority Priority of GDMA channel, higher value means higher priority
  212. * @return
  213. * - ESP_OK: Set GDMA channel priority successfully
  214. * - ESP_ERR_INVALID_ARG: Set GDMA channel priority failed because of invalid argument, e.g. priority out of range [0,GDMA_LL_CHANNEL_MAX_PRIORITY]
  215. * - ESP_FAIL: Set GDMA channel priority failed because of other error
  216. */
  217. esp_err_t gdma_set_priority(gdma_channel_handle_t dma_chan, uint32_t priority);
  218. /**
  219. * @brief Delete GDMA channel
  220. * @note If you call `gdma_new_channel` several times for a same peripheral, make sure you call this API the same times.
  221. *
  222. * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel`
  223. * @return
  224. * - ESP_OK: Delete GDMA channel successfully
  225. * - ESP_ERR_INVALID_ARG: Delete GDMA channel failed because of invalid argument
  226. * - ESP_FAIL: Delete GDMA channel failed because of other error
  227. */
  228. esp_err_t gdma_del_channel(gdma_channel_handle_t dma_chan);
  229. /**
  230. * @brief Get the channel ID
  231. *
  232. * @note This API breaks the encapsulation of GDMA Channel Object.
  233. * With the returned channel ID, you can even bypass all other GDMA driver API and access Low Level API directly.
  234. *
  235. * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel`
  236. * @param[out] channel_id Returned channel ID
  237. * @return
  238. * - ESP_OK: Get GDMA channel ID successfully
  239. * - ESP_ERR_INVALID_ARG: Get GDMA channel ID failed because of invalid argument
  240. * - ESP_FAIL: Get GDMA channel ID failed because of other error
  241. */
  242. esp_err_t gdma_get_channel_id(gdma_channel_handle_t dma_chan, int *channel_id);
  243. /**
  244. * @brief Set GDMA event callbacks for TX channel
  245. * @note This API will install GDMA interrupt service for the channel internally
  246. *
  247. * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel`
  248. * @param[in] cbs Group of callback functions
  249. * @param[in] user_data User data, which will be passed to callback functions directly
  250. * @return
  251. * - ESP_OK: Set event callbacks successfully
  252. * - ESP_ERR_INVALID_ARG: Set event callbacks failed because of invalid argument
  253. * - ESP_FAIL: Set event callbacks failed because of other error
  254. */
  255. esp_err_t gdma_register_tx_event_callbacks(gdma_channel_handle_t dma_chan, gdma_tx_event_callbacks_t *cbs, void *user_data);
  256. /**
  257. * @brief Set GDMA event callbacks for RX channel
  258. * @note This API will install GDMA interrupt service for the channel internally
  259. *
  260. * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel`
  261. * @param[in] cbs Group of callback functions
  262. * @param[in] user_data User data, which will be passed to callback functions directly
  263. * @return
  264. * - ESP_OK: Set event callbacks successfully
  265. * - ESP_ERR_INVALID_ARG: Set event callbacks failed because of invalid argument
  266. * - ESP_FAIL: Set event callbacks failed because of other error
  267. */
  268. esp_err_t gdma_register_rx_event_callbacks(gdma_channel_handle_t dma_chan, gdma_rx_event_callbacks_t *cbs, void *user_data);
  269. /**
  270. * @brief Set DMA descriptor address and start engine
  271. *
  272. * @note This function is allowed to run within ISR context
  273. * @note This function is also allowed to run when Cache is disabled, if `CONFIG_GDMA_CTRL_FUNC_IN_IRAM` is enabled
  274. *
  275. * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel`
  276. * @param[in] desc_base_addr Base address of descriptors (usually the descriptors are chained into a link or ring)
  277. * @return
  278. * - ESP_OK: Start DMA engine successfully
  279. * - ESP_ERR_INVALID_ARG: Start DMA engine failed because of invalid argument
  280. * - ESP_ERR_INVALID_STATE: Start DMA engine failed because of invalid state, e.g. the channel is controlled by ETM, so can't start it manually
  281. * - ESP_FAIL: Start DMA engine failed because of other error
  282. */
  283. esp_err_t gdma_start(gdma_channel_handle_t dma_chan, intptr_t desc_base_addr);
  284. /**
  285. * @brief Stop DMA engine
  286. *
  287. * @note This function is allowed to run within ISR context
  288. * @note This function is also allowed to run when Cache is disabled, if `CONFIG_GDMA_CTRL_FUNC_IN_IRAM` is enabled
  289. *
  290. * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel`
  291. * @return
  292. * - ESP_OK: Stop DMA engine successfully
  293. * - ESP_ERR_INVALID_ARG: Stop DMA engine failed because of invalid argument
  294. * - ESP_ERR_INVALID_STATE: Stop DMA engine failed because of invalid state, e.g. the channel is controlled by ETM, so can't stop it manually
  295. * - ESP_FAIL: Stop DMA engine failed because of other error
  296. */
  297. esp_err_t gdma_stop(gdma_channel_handle_t dma_chan);
  298. /**
  299. * @brief Make the appended descriptors be aware to the DMA engine
  300. *
  301. * @note This function is allowed to run within ISR context
  302. * @note This function is also allowed to run when Cache is disabled, if `CONFIG_GDMA_CTRL_FUNC_IN_IRAM` is enabled
  303. * @note This API could also resume a paused DMA engine, make sure new descriptors have been appended to the descriptor chain before calling it.
  304. *
  305. * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel`
  306. * @return
  307. * - ESP_OK: Send append command to DMA engine successfully
  308. * - ESP_ERR_INVALID_ARG: Send append command to DMA engine failed because of invalid argument
  309. * - ESP_FAIL: Send append command to DMA engine failed because of other error
  310. */
  311. esp_err_t gdma_append(gdma_channel_handle_t dma_chan);
  312. /**
  313. * @brief Reset DMA channel FIFO and internal finite state machine
  314. *
  315. * @note This function is allowed to run within ISR context
  316. * @note This function is also allowed to run when Cache is disabled, if `CONFIG_GDMA_CTRL_FUNC_IN_IRAM` is enabled
  317. * @note Resetting a DMA channel won't break the connection with the target peripheral
  318. *
  319. * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel`
  320. * @return
  321. * - ESP_OK: DMA channel reset successfully
  322. * - ESP_ERR_INVALID_ARG: DMA channel reset failed due to invalid arguments
  323. * - ESP_FAIL: DMA channel reset failed due to other errors
  324. */
  325. esp_err_t gdma_reset(gdma_channel_handle_t dma_chan);
  326. #if SOC_GDMA_SUPPORT_ETM
  327. /**
  328. * @brief GDMA ETM event configuration
  329. */
  330. typedef struct {
  331. gdma_etm_event_type_t event_type; /*!< GDMA ETM event type */
  332. } gdma_etm_event_config_t;
  333. /**
  334. * @brief Get the ETM event for GDMA channel
  335. *
  336. * @note The created ETM event object can be deleted later by calling `esp_etm_del_event`
  337. *
  338. * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel`
  339. * @param[in] config GDMA ETM event configuration
  340. * @param[out] out_event Returned ETM event handle
  341. * @return
  342. * - ESP_OK: Get ETM event successfully
  343. * - ESP_ERR_INVALID_ARG: Get ETM event failed because of invalid argument
  344. * - ESP_ERR_NOT_SUPPORTED: Get ETM event failed because the GDMA hardware doesn't support ETM event
  345. * - ESP_FAIL: Get ETM event failed because of other error
  346. */
  347. esp_err_t gdma_new_etm_event(gdma_channel_handle_t dma_chan, const gdma_etm_event_config_t *config, esp_etm_event_handle_t *out_event);
  348. /**
  349. * @brief GDMA ETM task configuration
  350. */
  351. typedef struct {
  352. gdma_etm_task_type_t task_type; /*!< GDMA ETM task type */
  353. } gdma_etm_task_config_t;
  354. /**
  355. * @brief Get the ETM task for GDMA channel
  356. *
  357. * @note The created ETM task object can be deleted later by calling `esp_etm_del_task`
  358. * @note If the GDMA task (e.g. start/stop) is controlled by ETM, then you can't use `gdma_start`/`gdma_stop` to control it.
  359. *
  360. * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel`
  361. * @param[in] config GDMA ETM task configuration
  362. * @param[out] out_task Returned ETM task handle
  363. * @return
  364. * - ESP_OK: Get ETM task successfully
  365. * - ESP_ERR_INVALID_ARG: Get ETM task failed because of invalid argument
  366. * - ESP_ERR_NOT_SUPPORTED: Get ETM task failed because the gdma hardware doesn't support ETM task
  367. * - ESP_FAIL: Get ETM task failed because of other error
  368. */
  369. esp_err_t gdma_new_etm_task(gdma_channel_handle_t dma_chan, const gdma_etm_task_config_t *config, esp_etm_task_handle_t *out_task);
  370. #endif // SOC_GDMA_SUPPORT_ETM
  371. /**
  372. * @brief Get the mask of free M2M trigger IDs
  373. *
  374. * @note On some ESP targets (e.g. ESP32C3/S3), DMA trigger used for memory copy can be any of valid peripheral's trigger ID,
  375. * which can bring conflict if the peripheral is also using the same trigger ID. This function can return the free IDs
  376. * for memory copy, at the runtime.
  377. *
  378. * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel`
  379. * @param[out] mask Returned mask of free M2M trigger IDs
  380. * @return
  381. * - ESP_OK: Get free M2M trigger IDs successfully
  382. * - ESP_ERR_INVALID_ARG: Get free M2M trigger IDs failed because of invalid argument
  383. * - ESP_FAIL: Get free M2M trigger IDs failed because of other error
  384. */
  385. esp_err_t gdma_get_free_m2m_trig_id_mask(gdma_channel_handle_t dma_chan, uint32_t *mask);
  386. #if SOC_GDMA_SUPPORT_CRC
  387. /**
  388. * @brief CRC Calculator configuration
  389. */
  390. typedef struct {
  391. uint32_t init_value; /*!< CRC initial value */
  392. uint32_t crc_bit_width; /*!< CRC bit width */
  393. uint32_t poly_hex; /*!< Polynomial Formula, in hex */
  394. bool reverse_data_mask; /*!< Reverse data mask, used when you want to reverse the input data (a.k.a, refin) */
  395. } gdma_crc_calculator_config_t;
  396. /**
  397. * @brief Configure CRC Calculator
  398. *
  399. * @note This function must be called before `gdma_start`.
  400. * @note The CRC Calculator will reset itself automatically if the DMA stops and starts again.
  401. *
  402. * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel`
  403. * @param[in] config CRC Calculator configuration
  404. * @return
  405. * - ESP_OK: Configure CRC Calculator successfully
  406. * - ESP_ERR_INVALID_ARG: Configure CRC Calculator failed because of invalid argument
  407. * - ESP_FAIL: Configure CRC Calculator failed because of other error
  408. */
  409. esp_err_t gdma_config_crc_calculator(gdma_channel_handle_t dma_chan, const gdma_crc_calculator_config_t *config);
  410. /**
  411. * @brief Get CRC Calculator result
  412. *
  413. * @note You need to call this function before a new DMA transaction starts, otherwise the CRC results may be overridden.
  414. *
  415. * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel`
  416. * @param[out] result Returned CRC result
  417. * @return
  418. * - ESP_OK: Get CRC result successfully
  419. * - ESP_ERR_INVALID_ARG: Get CRC result failed because of invalid argument
  420. * - ESP_FAIL: Get CRC result failed because of other error
  421. */
  422. esp_err_t gdma_crc_get_result(gdma_channel_handle_t dma_chan, uint32_t *result);
  423. #endif // SOC_GDMA_SUPPORT_CRC
  424. #ifdef __cplusplus
  425. }
  426. #endif