2021-05-23 19:50:04 -04:00
/*
* SPDX - FileCopyrightText : 2020 - 2021 Espressif Systems ( Shanghai ) CO LTD
*
* SPDX - License - Identifier : Apache - 2.0
*/
2020-12-09 07:29:26 -05:00
// DO NOT USE THESE APIS IN ANY APPLICATIONS
// GDMA driver is not public for end users, but for ESP-IDF developpers.
# pragma once
# include <stdbool.h>
# include "soc/gdma_channel.h"
2023-01-19 21:49:43 -05:00
# include "hal/gdma_types.h"
2020-12-09 07:29:26 -05:00
# include "esp_err.h"
# ifdef __cplusplus
extern " C " {
# endif
/**
* @ brief Type of GDMA channel handle
*
*/
typedef struct gdma_channel_t * gdma_channel_handle_t ;
/**
* @ brief Collection of configuration items that used for allocating GDMA channel
*
*/
typedef struct {
gdma_channel_handle_t sibling_chan ; /*!< DMA sibling channel handle (NULL means having sibling is not necessary) */
gdma_channel_direction_t direction ; /*!< DMA channel direction */
struct {
2021-06-23 02:10:07 -04:00
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 */
2020-12-09 07:29:26 -05:00
} flags ;
} gdma_channel_alloc_config_t ;
2021-06-23 02:10:07 -04:00
/**
* @ brief GDMA transfer ability
*
* @ note The alignment set in this structure is * * not * * a guarantee that gdma driver will take care of the nonalignment cases .
* Actually the GDMA driver has no knowledge about the DMA buffer ( address and size ) used by upper layer .
* So it ' s the responsibility of the * * upper layer * * to take care of the buffer address and size .
*
*/
typedef struct {
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 */
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 */
} gdma_transfer_ability_t ;
2020-12-09 07:29:26 -05:00
/**
* @ brief Type of GDMA event data
*
*/
typedef struct {
union {
intptr_t rx_eof_desc_addr ; /*!< EOF descriptor address of RX channel */
intptr_t tx_eof_desc_addr ; /*!< EOF descriptor address of TX channel */
} ;
} gdma_event_data_t ;
/**
* @ brief Type of GDMA event callback
* @ param dma_chan GDMA channel handle , created from ` gdma_new_channel `
* @ param event_data GDMA event data
* @ param user_data User registered data from ` gdma_register_tx_event_callbacks ` or ` gdma_register_rx_event_callbacks `
*
2021-06-23 02:10:07 -04:00
* @ return Whether a task switch is needed after the callback function returns ,
* this is usually due to the callback wakes up some high priority task .
*
2020-12-09 07:29:26 -05:00
*/
typedef bool ( * gdma_event_callback_t ) ( gdma_channel_handle_t dma_chan , gdma_event_data_t * event_data , void * user_data ) ;
/**
* @ brief Group of supported GDMA TX callbacks
* @ note The callbacks are all running under ISR environment
*
*/
typedef struct {
gdma_event_callback_t on_trans_eof ; /*!< Invoked when TX engine meets EOF descriptor */
} gdma_tx_event_callbacks_t ;
/**
* @ brief Group of supported GDMA RX callbacks
* @ note The callbacks are all running under ISR environment
*
*/
typedef struct {
gdma_event_callback_t on_recv_eof ; /*!< Invoked when RX engine meets EOF descriptor */
} gdma_rx_event_callbacks_t ;
/**
* @ brief Type of GDMA engine trigger
* @ note It ' s recommended to initialize this structure with ` GDMA_MAKE_TRIGGER ` .
*
*/
typedef struct {
gdma_trigger_peripheral_t periph ; /*!< Target peripheral which will trigger DMA operations */
2023-01-09 21:28:41 -05:00
int instance_id ; /*!< Peripheral instance ID. Supported IDs are listed in `soc/gdma_channel.h`, e.g. SOC_GDMA_TRIG_PERIPH_UHCI0 */
2020-12-09 07:29:26 -05:00
} gdma_trigger_t ;
/**
* @ brief Helper macro to initialize GDMA trigger
* @ note value of ` peri ` must be selected from ` gdma_trigger_peripheral_t ` enum .
2023-01-09 21:28:41 -05:00
* e . g . GDMA_MAKE_TRIGGER ( GDMA_TRIG_PERIPH_I2S , 0 )
2020-12-09 07:29:26 -05:00
*
*/
# define GDMA_MAKE_TRIGGER(peri, id) \
( gdma_trigger_t ) { . periph = peri , . instance_id = SOC_ # # peri # # id }
/**
* @ brief A collection of strategy item that each GDMA channel could apply
*
*/
typedef struct {
bool owner_check ; /*!< If set / clear, DMA channel enables / disables checking owner validity */
bool auto_update_desc ; /*!< If set / clear, DMA channel enables / disables hardware to update descriptor automatically (TX channel only) */
} gdma_strategy_config_t ;
/**
* @ brief Create GDMA channel
* @ note This API won ' t install interrupt service for the allocated channel .
* If interrupt service is needed , user has to register GDMA event callback by ` gdma_register_tx_event_callbacks ` or ` gdma_register_rx_event_callbacks ` .
*
* @ param [ in ] config Pointer to a collection of configurations for allocating GDMA channel
* @ param [ out ] ret_chan Returnned channel handle
* @ return
* - ESP_OK : Create DMA channel successfully
* - ESP_ERR_INVALID_ARG : Create DMA channel failed because of invalid argument
* - ESP_ERR_NO_MEM : Create DMA channel failed because out of memory
* - ESP_FAIL : Create DMA channel failed because of other error
*/
esp_err_t gdma_new_channel ( const gdma_channel_alloc_config_t * config , gdma_channel_handle_t * ret_chan ) ;
/**
* @ brief Connect GDMA channel to trigger peripheral
*
* @ note Suggest to use helper macro ` GDMA_MAKE_TRIGGER ` to construct parameter ` trig_periph ` . e . g . GDMA_MAKE_TRIGGER ( GDMA_TRIG_PERIPH_SHA , 0 )
2021-03-22 09:58:04 -04:00
* @ note Connecting to a peripheral will also reset the DMA FIFO and FSM automatically
2020-12-09 07:29:26 -05:00
*
* @ param [ in ] dma_chan GDMA channel handle , allocated by ` gdma_new_channel `
* @ param [ in ] trig_periph GDMA trigger peripheral
* @ return
* - ESP_OK : Connect GDMA channel successfully
* - ESP_ERR_INVALID_ARG : Connect GDMA channel failed because of invalid argument
* - ESP_ERR_INVALID_STATE : Connect GDMA channel failed because DMA channel is working with another peripheral
* - ESP_FAIL : Connect GDMA channel failed because of other error
*/
esp_err_t gdma_connect ( gdma_channel_handle_t dma_chan , gdma_trigger_t trig_periph ) ;
/**
* @ brief Disconnect GMA channel from peripheral
*
* @ param [ in ] dma_chan GDMA channel handle , allocated by ` gdma_new_channel `
* @ return
* - ESP_OK : Disconnect GDMA channel successfully
* - ESP_ERR_INVALID_ARG : Disconnect GDMA channel failed because of invalid argument
* - ESP_ERR_INVALID_STATE : Disconnect GDMA channel failed because DMA channel is not connected to any peripheral
* - ESP_FAIL : Disconnect DMA channel failed because of other error
*/
esp_err_t gdma_disconnect ( gdma_channel_handle_t dma_chan ) ;
2021-06-23 02:10:07 -04:00
/**
* @ brief Set DMA channel transfer ability
*
* @ param [ in ] dma_chan GDMA channel handle , allocated by ` gdma_new_channel `
* @ param [ in ] ability Transfer ability , e . g . alignment
* @ return
* - ESP_OK : Set DMA channel transfer ability successfully
* - ESP_ERR_INVALID_ARG : Set DMA channel transfer ability failed because of invalid argument
* - ESP_FAIL : Set DMA channel transfer ability failed because of other error
*/
esp_err_t gdma_set_transfer_ability ( gdma_channel_handle_t dma_chan , const gdma_transfer_ability_t * ability ) ;
2020-12-09 07:29:26 -05:00
/**
* @ brief Apply channel strategy for GDMA channel
*
* @ param dma_chan GDMA channel handle , allocated by ` gdma_new_channel `
* @ param config Configuration of GDMA channel strategy
* - ESP_OK : Apply channel strategy successfully
* - ESP_ERR_INVALID_ARG : Apply channel strategy failed because of invalid argument
* - ESP_FAIL : Apply channel strategy failed because of other error
*/
esp_err_t gdma_apply_strategy ( gdma_channel_handle_t dma_chan , const gdma_strategy_config_t * config ) ;
/**
* @ brief Delete GDMA channel
* @ note If you call ` gdma_new_channel ` several times for a same peripheral , make sure you call this API the same times .
*
* @ param [ in ] dma_chan GDMA channel handle , allocated by ` gdma_new_channel `
* @ return
* - ESP_OK : Delete GDMA channel successfully
* - ESP_ERR_INVALID_ARG : Delete GDMA channel failed because of invalid argument
* - ESP_FAIL : Delete GDMA channel failed because of other error
*/
esp_err_t gdma_del_channel ( gdma_channel_handle_t dma_chan ) ;
/**
* @ brief Get the channel ID
*
* @ note This API breaks the encapsulation of GDMA Channel Object .
* With the returned channel ID , you can even bypass all other GDMA driver API and access Low Level API directly .
*
* @ param [ in ] dma_chan GDMA channel handle , allocated by ` gdma_new_channel `
* @ param [ out ] channel_id Returned channel ID
* @ return
* - ESP_OK : Get GDMA channel ID successfully
* - ESP_ERR_INVALID_ARG : Get GDMA channel ID failed because of invalid argument
* - ESP_FAIL : Get GDMA channel ID failed because of other error
*/
esp_err_t gdma_get_channel_id ( gdma_channel_handle_t dma_chan , int * channel_id ) ;
/**
* @ brief Set GDMA event callbacks for TX channel
* @ note This API will install GDMA interrupt service for the channel internally
*
* @ param [ in ] dma_chan GDMA channel handle , allocated by ` gdma_new_channel `
* @ param [ in ] cbs Group of callback functions
* @ param [ in ] user_data User data , which will be passed to callback functions directly
* @ return
* - ESP_OK : Set event callbacks successfully
* - ESP_ERR_INVALID_ARG : Set event callbacks failed because of invalid argument
* - ESP_FAIL : Set event callbacks failed because of other error
*/
esp_err_t gdma_register_tx_event_callbacks ( gdma_channel_handle_t dma_chan , gdma_tx_event_callbacks_t * cbs , void * user_data ) ;
/**
* @ brief Set GDMA event callbacks for RX channel
* @ note This API will install GDMA interrupt service for the channel internally
*
* @ param [ in ] dma_chan GDMA channel handle , allocated by ` gdma_new_channel `
* @ param [ in ] cbs Group of callback functions
* @ param [ in ] user_data User data , which will be passed to callback functions directly
* @ return
* - ESP_OK : Set event callbacks successfully
* - ESP_ERR_INVALID_ARG : Set event callbacks failed because of invalid argument
* - ESP_FAIL : Set event callbacks failed because of other error
*/
esp_err_t gdma_register_rx_event_callbacks ( gdma_channel_handle_t dma_chan , gdma_rx_event_callbacks_t * cbs , void * user_data ) ;
/**
* @ brief Set DMA descriptor address and start engine
*
2022-04-07 03:31:49 -04:00
* @ note This function is allowed to run within ISR context
* @ note This function is also allowed to run when Cache is disabled , if ` CONFIG_GDMA_CTRL_FUNC_IN_IRAM ` is enabled
*
2020-12-09 07:29:26 -05:00
* @ param [ in ] dma_chan GDMA channel handle , allocated by ` gdma_new_channel `
* @ param [ in ] desc_base_addr Base address of descriptors ( usually the descriptors are chained into a link or ring )
* @ return
* - ESP_OK : Start DMA engine successfully
* - ESP_ERR_INVALID_ARG : Start DMA engine failed because of invalid argument
* - ESP_FAIL : Start DMA engine failed because of other error
*/
esp_err_t gdma_start ( gdma_channel_handle_t dma_chan , intptr_t desc_base_addr ) ;
/**
* @ brief Stop DMA engine
*
2022-04-07 03:31:49 -04:00
* @ note This function is allowed to run within ISR context
* @ note This function is also allowed to run when Cache is disabled , if ` CONFIG_GDMA_CTRL_FUNC_IN_IRAM ` is enabled
*
2020-12-09 07:29:26 -05:00
* @ param [ in ] dma_chan GDMA channel handle , allocated by ` gdma_new_channel `
* @ return
* - ESP_OK : Stop DMA engine successfully
* - ESP_ERR_INVALID_ARG : Stop DMA engine failed because of invalid argument
* - ESP_FAIL : Stop DMA engine failed because of other error
*/
esp_err_t gdma_stop ( gdma_channel_handle_t dma_chan ) ;
/**
* @ brief Make the appended descriptors be aware to the DMA engine
2022-04-07 03:31:49 -04:00
*
* @ note This function is allowed to run within ISR context
* @ note This function is also allowed to run when Cache is disabled , if ` CONFIG_GDMA_CTRL_FUNC_IN_IRAM ` is enabled
2020-12-09 07:29:26 -05:00
* @ note This API could also resume a paused DMA engine , make sure new descriptors have been appended to the descriptor chain before calling it .
*
* @ param [ in ] dma_chan GDMA channel handle , allocated by ` gdma_new_channel `
* @ return
* - ESP_OK : Send append command to DMA engine successfully
* - ESP_ERR_INVALID_ARG : Send append command to DMA engine failed because of invalid argument
* - ESP_FAIL : Send append command to DMA engine failed because of other error
*/
esp_err_t gdma_append ( gdma_channel_handle_t dma_chan ) ;
2021-03-22 09:58:04 -04:00
/**
* @ brief Reset DMA channel FIFO and internal finite state machine
2022-04-07 03:31:49 -04:00
*
* @ note This function is allowed to run within ISR context
* @ note This function is also allowed to run when Cache is disabled , if ` CONFIG_GDMA_CTRL_FUNC_IN_IRAM ` is enabled
2021-03-22 09:58:04 -04:00
* @ note Resetting a DMA channel won ' t break the connection with the target peripheral
*
* @ param [ in ] dma_chan GDMA channel handle , allocated by ` gdma_new_channel `
* @ return
* - ESP_OK : DMA channel reset successfully
* - ESP_ERR_INVALID_ARG : DMA channel reset failed due to invalid arguments
* - ESP_FAIL : DMA channel reset failed due to other errors
*/
esp_err_t gdma_reset ( gdma_channel_handle_t dma_chan ) ;
2023-01-19 21:49:43 -05:00
/**
* @ brief Get the mask of free M2M trigger IDs
*
* @ note On some ESP targets ( e . g . ESP32C3 / S3 ) , DMA trigger used for memory copy can be any of valid peripheral ' s trigger ID ,
* which can bring conflict if the peripheral is also using the same trigger ID . This function can return the free IDs
* for memory copy , at the runtime .
*
* @ param [ in ] dma_chan GDMA channel handle , allocated by ` gdma_new_channel `
* @ param [ out ] mask Returned mask of free M2M trigger IDs
* @ return
* - ESP_OK : Get free M2M trigger IDs successfully
* - ESP_ERR_INVALID_ARG : Get free M2M trigger IDs failed because of invalid argument
* - ESP_FAIL : Get free M2M trigger IDs failed because of other error
*/
esp_err_t gdma_get_free_m2m_trig_id_mask ( gdma_channel_handle_t dma_chan , uint32_t * mask ) ;
2020-12-09 07:29:26 -05:00
# ifdef __cplusplus
}
# endif