1 /* 2 * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 // DO NOT USE THESE APIS IN ANY APPLICATIONS 8 // GDMA driver is not public for end users, but for ESP-IDF developpers. 9 10 #pragma once 11 12 #include <stdbool.h> 13 #include "soc/gdma_channel.h" 14 #include "esp_err.h" 15 16 #ifdef __cplusplus 17 extern "C" { 18 #endif 19 20 /** 21 * @brief Type of GDMA channel handle 22 * 23 */ 24 typedef struct gdma_channel_t *gdma_channel_handle_t; 25 26 /** 27 * @brief Enumeration of peripherals which have the DMA capability 28 * @note Some peripheral might not be available on certain chip, please refer to `soc_caps.h` for detail. 29 * 30 */ 31 typedef enum { 32 GDMA_TRIG_PERIPH_M2M, /*!< GDMA trigger peripheral: M2M */ 33 GDMA_TRIG_PERIPH_UART, /*!< GDMA trigger peripheral: UART */ 34 GDMA_TRIG_PERIPH_SPI, /*!< GDMA trigger peripheral: SPI */ 35 GDMA_TRIG_PERIPH_I2S, /*!< GDMA trigger peripheral: I2S */ 36 GDMA_TRIG_PERIPH_AES, /*!< GDMA trigger peripheral: AES */ 37 GDMA_TRIG_PERIPH_SHA, /*!< GDMA trigger peripheral: SHA */ 38 GDMA_TRIG_PERIPH_ADC, /*!< GDMA trigger peripheral: ADC */ 39 GDMA_TRIG_PERIPH_DAC, /*!< GDMA trigger peripheral: DAC */ 40 GDMA_TRIG_PERIPH_LCD, /*!< GDMA trigger peripheral: LCD */ 41 GDMA_TRIG_PERIPH_CAM, /*!< GDMA trigger peripheral: CAM */ 42 GDMA_TRIG_PERIPH_RMT, /*!< GDMA trigger peripheral: RMT */ 43 } gdma_trigger_peripheral_t; 44 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 /** 55 * @brief Collection of configuration items that used for allocating GDMA channel 56 * 57 */ 58 typedef struct { 59 gdma_channel_handle_t sibling_chan; /*!< DMA sibling channel handle (NULL means having sibling is not necessary) */ 60 gdma_channel_direction_t direction; /*!< DMA channel direction */ 61 struct { 62 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 */ 63 } flags; 64 } gdma_channel_alloc_config_t; 65 66 /** 67 * @brief GDMA transfer ability 68 * 69 * @note The alignment set in this structure is **not** a guarantee that gdma driver will take care of the nonalignment cases. 70 * Actually the GDMA driver has no knowledge about the DMA buffer (address and size) used by upper layer. 71 * So it's the responsibility of the **upper layer** to take care of the buffer address and size. 72 * 73 */ 74 typedef struct { 75 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 */ 76 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 */ 77 } gdma_transfer_ability_t; 78 79 /** 80 * @brief Type of GDMA event data 81 * 82 */ 83 typedef struct { 84 union { 85 intptr_t rx_eof_desc_addr; /*!< EOF descriptor address of RX channel */ 86 intptr_t tx_eof_desc_addr; /*!< EOF descriptor address of TX channel */ 87 }; 88 } gdma_event_data_t; 89 90 /** 91 * @brief Type of GDMA event callback 92 * @param dma_chan GDMA channel handle, created from `gdma_new_channel` 93 * @param event_data GDMA event data 94 * @param user_data User registered data from `gdma_register_tx_event_callbacks` or `gdma_register_rx_event_callbacks` 95 * 96 * @return Whether a task switch is needed after the callback function returns, 97 * this is usually due to the callback wakes up some high priority task. 98 * 99 */ 100 typedef bool (*gdma_event_callback_t)(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data); 101 102 /** 103 * @brief Group of supported GDMA TX callbacks 104 * @note The callbacks are all running under ISR environment 105 * 106 */ 107 typedef struct { 108 gdma_event_callback_t on_trans_eof; /*!< Invoked when TX engine meets EOF descriptor */ 109 } gdma_tx_event_callbacks_t; 110 111 /** 112 * @brief Group of supported GDMA RX callbacks 113 * @note The callbacks are all running under ISR environment 114 * 115 */ 116 typedef struct { 117 gdma_event_callback_t on_recv_eof; /*!< Invoked when RX engine meets EOF descriptor */ 118 } gdma_rx_event_callbacks_t; 119 120 /** 121 * @brief Type of GDMA engine trigger 122 * @note It's recommended to initialize this structure with `GDMA_MAKE_TRIGGER`. 123 * 124 */ 125 typedef struct { 126 gdma_trigger_peripheral_t periph; /*!< Target peripheral which will trigger DMA operations */ 127 int instance_id; /*!< Peripheral instance ID. Supported IDs are listed in `soc/gdma_channel.h`, e.g. SOC_GDMA_TRIG_PERIPH_UART0 */ 128 } gdma_trigger_t; 129 130 /** 131 * @brief Helper macro to initialize GDMA trigger 132 * @note value of `peri` must be selected from `gdma_trigger_peripheral_t` enum. 133 * e.g. GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_UART,0) 134 * 135 */ 136 #define GDMA_MAKE_TRIGGER(peri, id) \ 137 (gdma_trigger_t) { .periph = peri, .instance_id = SOC_##peri##id } 138 139 /** 140 * @brief A collection of strategy item that each GDMA channel could apply 141 * 142 */ 143 typedef struct { 144 bool owner_check; /*!< If set / clear, DMA channel enables / disables checking owner validity */ 145 bool auto_update_desc; /*!< If set / clear, DMA channel enables / disables hardware to update descriptor automatically (TX channel only) */ 146 } gdma_strategy_config_t; 147 148 /** 149 * @brief Create GDMA channel 150 * @note This API won't install interrupt service for the allocated channel. 151 * If interrupt service is needed, user has to register GDMA event callback by `gdma_register_tx_event_callbacks` or `gdma_register_rx_event_callbacks`. 152 * 153 * @param[in] config Pointer to a collection of configurations for allocating GDMA channel 154 * @param[out] ret_chan Returnned channel handle 155 * @return 156 * - ESP_OK: Create DMA channel successfully 157 * - ESP_ERR_INVALID_ARG: Create DMA channel failed because of invalid argument 158 * - ESP_ERR_NO_MEM: Create DMA channel failed because out of memory 159 * - ESP_FAIL: Create DMA channel failed because of other error 160 */ 161 esp_err_t gdma_new_channel(const gdma_channel_alloc_config_t *config, gdma_channel_handle_t *ret_chan); 162 163 /** 164 * @brief Connect GDMA channel to trigger peripheral 165 * 166 * @note Suggest to use helper macro `GDMA_MAKE_TRIGGER` to construct parameter `trig_periph`. e.g. GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_SHA,0) 167 * @note Connecting to a peripheral will also reset the DMA FIFO and FSM automatically 168 * 169 * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel` 170 * @param[in] trig_periph GDMA trigger peripheral 171 * @return 172 * - ESP_OK: Connect GDMA channel successfully 173 * - ESP_ERR_INVALID_ARG: Connect GDMA channel failed because of invalid argument 174 * - ESP_ERR_INVALID_STATE: Connect GDMA channel failed because DMA channel is working with another peripheral 175 * - ESP_FAIL: Connect GDMA channel failed because of other error 176 */ 177 esp_err_t gdma_connect(gdma_channel_handle_t dma_chan, gdma_trigger_t trig_periph); 178 179 /** 180 * @brief Disconnect GMA channel from peripheral 181 * 182 * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel` 183 * @return 184 * - ESP_OK: Disconnect GDMA channel successfully 185 * - ESP_ERR_INVALID_ARG: Disconnect GDMA channel failed because of invalid argument 186 * - ESP_ERR_INVALID_STATE: Disconnect GDMA channel failed because DMA channel is not connected to any peripheral 187 * - ESP_FAIL: Disconnect DMA channel failed because of other error 188 */ 189 esp_err_t gdma_disconnect(gdma_channel_handle_t dma_chan); 190 191 /** 192 * @brief Set DMA channel transfer ability 193 * 194 * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel` 195 * @param[in] ability Transfer ability, e.g. alignment 196 * @return 197 * - ESP_OK: Set DMA channel transfer ability successfully 198 * - ESP_ERR_INVALID_ARG: Set DMA channel transfer ability failed because of invalid argument 199 * - ESP_FAIL: Set DMA channel transfer ability failed because of other error 200 */ 201 esp_err_t gdma_set_transfer_ability(gdma_channel_handle_t dma_chan, const gdma_transfer_ability_t *ability); 202 203 /** 204 * @brief Apply channel strategy for GDMA channel 205 * 206 * @param dma_chan GDMA channel handle, allocated by `gdma_new_channel` 207 * @param config Configuration of GDMA channel strategy 208 * - ESP_OK: Apply channel strategy successfully 209 * - ESP_ERR_INVALID_ARG: Apply channel strategy failed because of invalid argument 210 * - ESP_FAIL: Apply channel strategy failed because of other error 211 */ 212 esp_err_t gdma_apply_strategy(gdma_channel_handle_t dma_chan, const gdma_strategy_config_t *config); 213 214 /** 215 * @brief Delete GDMA channel 216 * @note If you call `gdma_new_channel` several times for a same peripheral, make sure you call this API the same times. 217 * 218 * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel` 219 * @return 220 * - ESP_OK: Delete GDMA channel successfully 221 * - ESP_ERR_INVALID_ARG: Delete GDMA channel failed because of invalid argument 222 * - ESP_FAIL: Delete GDMA channel failed because of other error 223 */ 224 esp_err_t gdma_del_channel(gdma_channel_handle_t dma_chan); 225 226 /** 227 * @brief Get the channel ID 228 * 229 * @note This API breaks the encapsulation of GDMA Channel Object. 230 * With the returned channel ID, you can even bypass all other GDMA driver API and access Low Level API directly. 231 * 232 * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel` 233 * @param[out] channel_id Returned channel ID 234 * @return 235 * - ESP_OK: Get GDMA channel ID successfully 236 * - ESP_ERR_INVALID_ARG: Get GDMA channel ID failed because of invalid argument 237 * - ESP_FAIL: Get GDMA channel ID failed because of other error 238 */ 239 esp_err_t gdma_get_channel_id(gdma_channel_handle_t dma_chan, int *channel_id); 240 241 /** 242 * @brief Set GDMA event callbacks for TX channel 243 * @note This API will install GDMA interrupt service for the channel internally 244 * 245 * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel` 246 * @param[in] cbs Group of callback functions 247 * @param[in] user_data User data, which will be passed to callback functions directly 248 * @return 249 * - ESP_OK: Set event callbacks successfully 250 * - ESP_ERR_INVALID_ARG: Set event callbacks failed because of invalid argument 251 * - ESP_FAIL: Set event callbacks failed because of other error 252 */ 253 esp_err_t gdma_register_tx_event_callbacks(gdma_channel_handle_t dma_chan, gdma_tx_event_callbacks_t *cbs, void *user_data); 254 255 /** 256 * @brief Set GDMA event callbacks for RX channel 257 * @note This API will install GDMA interrupt service for the channel internally 258 * 259 * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel` 260 * @param[in] cbs Group of callback functions 261 * @param[in] user_data User data, which will be passed to callback functions directly 262 * @return 263 * - ESP_OK: Set event callbacks successfully 264 * - ESP_ERR_INVALID_ARG: Set event callbacks failed because of invalid argument 265 * - ESP_FAIL: Set event callbacks failed because of other error 266 */ 267 esp_err_t gdma_register_rx_event_callbacks(gdma_channel_handle_t dma_chan, gdma_rx_event_callbacks_t *cbs, void *user_data); 268 269 /** 270 * @brief Set DMA descriptor address and start engine 271 * 272 * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel` 273 * @param[in] desc_base_addr Base address of descriptors (usually the descriptors are chained into a link or ring) 274 * @return 275 * - ESP_OK: Start DMA engine successfully 276 * - ESP_ERR_INVALID_ARG: Start DMA engine failed because of invalid argument 277 * - ESP_FAIL: Start DMA engine failed because of other error 278 */ 279 esp_err_t gdma_start(gdma_channel_handle_t dma_chan, intptr_t desc_base_addr); 280 281 /** 282 * @brief Stop DMA engine 283 * 284 * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel` 285 * @return 286 * - ESP_OK: Stop DMA engine successfully 287 * - ESP_ERR_INVALID_ARG: Stop DMA engine failed because of invalid argument 288 * - ESP_FAIL: Stop DMA engine failed because of other error 289 */ 290 esp_err_t gdma_stop(gdma_channel_handle_t dma_chan); 291 292 /** 293 * @brief Make the appended descriptors be aware to the DMA engine 294 * @note This API could also resume a paused DMA engine, make sure new descriptors have been appended to the descriptor chain before calling it. 295 * 296 * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel` 297 * @return 298 * - ESP_OK: Send append command to DMA engine successfully 299 * - ESP_ERR_INVALID_ARG: Send append command to DMA engine failed because of invalid argument 300 * - ESP_FAIL: Send append command to DMA engine failed because of other error 301 */ 302 esp_err_t gdma_append(gdma_channel_handle_t dma_chan); 303 304 /** 305 * @brief Reset DMA channel FIFO and internal finite state machine 306 * @note Resetting a DMA channel won't break the connection with the target peripheral 307 * 308 * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel` 309 * @return 310 * - ESP_OK: DMA channel reset successfully 311 * - ESP_ERR_INVALID_ARG: DMA channel reset failed due to invalid arguments 312 * - ESP_FAIL: DMA channel reset failed due to other errors 313 */ 314 esp_err_t gdma_reset(gdma_channel_handle_t dma_chan); 315 316 #ifdef __cplusplus 317 } 318 #endif 319