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