From dbca74f1efda2444fc9c3baa493a9859eb2670ef Mon Sep 17 00:00:00 2001 From: morris Date: Fri, 20 Jan 2023 10:49:43 +0800 Subject: [PATCH] gdma: prevent mutli-channels connect to the same peripheral 1. add check in the gdma driver, to prevent multiple channels connecting to the same peripheral 2. memory copy DMA ID will occupy the peripheral's DMA ID on some ESP targets (e.g. esp32c3/s3). We should search for a free one when install async memcpy driver. Closes https://github.com/espressif/esp-idf/issues/10575 --- components/driver/i2s/i2s_common.c | 1 + .../dma/async_memcpy_impl_gdma.c | 13 ++- components/esp_hw_support/dma/gdma.c | 96 ++++++++++++++----- components/esp_hw_support/dma/gdma_priv.h | 4 +- .../esp_hw_support/include/esp_private/gdma.h | 44 ++++----- .../test_apps/dma/main/test_gdma.c | 19 ++-- components/hal/esp32c2/include/hal/gdma_ll.h | 41 +++++--- components/hal/esp32c3/include/hal/gdma_ll.h | 41 +++++--- components/hal/esp32c6/include/hal/apm_ll.h | 2 +- components/hal/esp32c6/include/hal/gdma_ll.h | 41 ++++---- components/hal/esp32h2/include/hal/apm_ll.h | 2 +- components/hal/esp32h2/include/hal/gdma_ll.h | 41 ++++---- components/hal/esp32h4/include/hal/gdma_ll.h | 41 +++++--- components/hal/esp32s3/include/hal/gdma_ll.h | 42 ++++---- components/hal/include/hal/gdma_types.h | 30 +++++- .../soc/esp32c6/include/soc/gdma_channel.h | 2 +- .../soc/esp32h2/include/soc/gdma_channel.h | 2 +- 17 files changed, 298 insertions(+), 164 deletions(-) diff --git a/components/driver/i2s/i2s_common.c b/components/driver/i2s/i2s_common.c index b7df13f663..6134fc8b39 100644 --- a/components/driver/i2s/i2s_common.c +++ b/components/driver/i2s/i2s_common.c @@ -934,6 +934,7 @@ esp_err_t i2s_del_channel(i2s_chan_handle_t handle) #endif if (handle->dma.dma_chan) { #if SOC_GDMA_SUPPORTED + gdma_disconnect(handle->dma.dma_chan); gdma_del_channel(handle->dma.dma_chan); #else esp_intr_free(handle->dma.dma_chan); diff --git a/components/esp_hw_support/dma/async_memcpy_impl_gdma.c b/components/esp_hw_support/dma/async_memcpy_impl_gdma.c index dd5d4a0f56..99825d96eb 100644 --- a/components/esp_hw_support/dma/async_memcpy_impl_gdma.c +++ b/components/esp_hw_support/dma/async_memcpy_impl_gdma.c @@ -51,8 +51,13 @@ esp_err_t async_memcpy_impl_init(async_memcpy_impl_t *impl) goto err; } - gdma_connect(impl->rx_channel, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_M2M, 0)); - gdma_connect(impl->tx_channel, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_M2M, 0)); + gdma_trigger_t m2m_trigger = GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_M2M, 0); + // get a free DMA trigger ID for memory copy + uint32_t free_m2m_id_mask = 0; + gdma_get_free_m2m_trig_id_mask(impl->tx_channel, &free_m2m_id_mask); + m2m_trigger.instance_id = __builtin_ctz(free_m2m_id_mask); + gdma_connect(impl->rx_channel, m2m_trigger); + gdma_connect(impl->tx_channel, m2m_trigger); gdma_strategy_config_t strategy_config = { .auto_update_desc = true, @@ -75,11 +80,9 @@ esp_err_t async_memcpy_impl_init(async_memcpy_impl_t *impl) gdma_apply_strategy(impl->rx_channel, &strategy_config); #if SOC_APM_SUPPORTED - // APM GDMA master for M2M should have the same offset of its GDMA trigger - ESP_STATIC_ASSERT((APM_LL_MASTER_GDMA_M2M - 16) == SOC_GDMA_TRIG_PERIPH_M2M0); // APM strategy: trusted mode // TODO: IDF-5354 GDMA for M2M usage only need read and write permissions, we should disable the execute permission by the APM controller - apm_ll_set_master_secure_mode(APM_LL_MASTER_GDMA_M2M, APM_LL_SECURE_MODE_TEE); + apm_ll_set_master_secure_mode(APM_LL_MASTER_GDMA + m2m_trigger.instance_id, APM_LL_SECURE_MODE_TEE); #endif // SOC_APM_SUPPORTED gdma_rx_event_callbacks_t cbs = { diff --git a/components/esp_hw_support/dma/gdma.c b/components/esp_hw_support/dma/gdma.c index 10be324835..101ccf4d39 100644 --- a/components/esp_hw_support/dma/gdma.c +++ b/components/esp_hw_support/dma/gdma.c @@ -182,53 +182,97 @@ err: esp_err_t gdma_connect(gdma_channel_handle_t dma_chan, gdma_trigger_t trig_periph) { - esp_err_t ret = ESP_OK; gdma_pair_t *pair = NULL; gdma_group_t *group = NULL; - ESP_GOTO_ON_FALSE(dma_chan, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); - ESP_GOTO_ON_FALSE(dma_chan->periph_id == GDMA_INVALID_PERIPH_TRIG, ESP_ERR_INVALID_STATE, err, TAG, "channel is using by peripheral: %d", dma_chan->periph_id); + ESP_RETURN_ON_FALSE(dma_chan, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + ESP_RETURN_ON_FALSE(dma_chan->periph_id == GDMA_INVALID_PERIPH_TRIG, ESP_ERR_INVALID_STATE, TAG, "channel is using by peripheral: %d", dma_chan->periph_id); pair = dma_chan->pair; group = pair->group; - - dma_chan->periph_id = trig_periph.instance_id; - // enable/disable m2m mode - gdma_ll_enable_m2m_mode(group->hal.dev, pair->pair_id, trig_periph.periph == GDMA_TRIG_PERIPH_M2M); + bool periph_conflict = false; if (dma_chan->direction == GDMA_CHANNEL_DIRECTION_TX) { - gdma_ll_tx_reset_channel(group->hal.dev, pair->pair_id); // reset channel - if (trig_periph.periph != GDMA_TRIG_PERIPH_M2M) { - gdma_ll_tx_connect_to_periph(group->hal.dev, pair->pair_id, trig_periph.instance_id); + if (trig_periph.instance_id >= 0) { + portENTER_CRITICAL(&group->spinlock); + if (group->tx_periph_in_use_mask & (1 << trig_periph.instance_id)) { + periph_conflict = true; + } else { + group->tx_periph_in_use_mask |= (1 << trig_periph.instance_id); + } + portEXIT_CRITICAL(&group->spinlock); + } + if (!periph_conflict) { + gdma_ll_tx_reset_channel(group->hal.dev, pair->pair_id); // reset channel + gdma_ll_tx_connect_to_periph(group->hal.dev, pair->pair_id, trig_periph.periph, trig_periph.instance_id); } } else { - gdma_ll_rx_reset_channel(group->hal.dev, pair->pair_id); // reset channel - if (trig_periph.periph != GDMA_TRIG_PERIPH_M2M) { - gdma_ll_rx_connect_to_periph(group->hal.dev, pair->pair_id, trig_periph.instance_id); + if (trig_periph.instance_id >= 0) { + portENTER_CRITICAL(&group->spinlock); + if (group->rx_periph_in_use_mask & (1 << trig_periph.instance_id)) { + periph_conflict = true; + } else { + group->rx_periph_in_use_mask |= (1 << trig_periph.instance_id); + } + portEXIT_CRITICAL(&group->spinlock); + } + if (!periph_conflict) { + gdma_ll_rx_reset_channel(group->hal.dev, pair->pair_id); // reset channel + gdma_ll_rx_connect_to_periph(group->hal.dev, pair->pair_id, trig_periph.periph, trig_periph.instance_id); } } -err: - return ret; + ESP_RETURN_ON_FALSE(!periph_conflict, ESP_ERR_INVALID_STATE, TAG, "peripheral %d is already used by another channel", trig_periph.instance_id); + dma_chan->periph_id = trig_periph.instance_id; + return ESP_OK; } esp_err_t gdma_disconnect(gdma_channel_handle_t dma_chan) { - esp_err_t ret = ESP_OK; gdma_pair_t *pair = NULL; gdma_group_t *group = NULL; - ESP_GOTO_ON_FALSE(dma_chan, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); - ESP_GOTO_ON_FALSE(dma_chan->periph_id != GDMA_INVALID_PERIPH_TRIG, ESP_ERR_INVALID_STATE, err, TAG, "no peripheral is connected to the channel"); + ESP_RETURN_ON_FALSE(dma_chan, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + ESP_RETURN_ON_FALSE(dma_chan->periph_id != GDMA_INVALID_PERIPH_TRIG, ESP_ERR_INVALID_STATE, TAG, "no peripheral is connected to the channel"); + + pair = dma_chan->pair; + group = pair->group; + int save_periph_id = dma_chan->periph_id; + + if (dma_chan->direction == GDMA_CHANNEL_DIRECTION_TX) { + if (save_periph_id >= 0) { + portENTER_CRITICAL(&group->spinlock); + group->tx_periph_in_use_mask &= ~(1 << save_periph_id); + portEXIT_CRITICAL(&group->spinlock); + } + gdma_ll_tx_disconnect_from_periph(group->hal.dev, pair->pair_id); + } else { + if (save_periph_id >= 0) { + portENTER_CRITICAL(&group->spinlock); + group->rx_periph_in_use_mask &= ~(1 << save_periph_id); + portEXIT_CRITICAL(&group->spinlock); + } + gdma_ll_rx_disconnect_from_periph(group->hal.dev, pair->pair_id); + } + + dma_chan->periph_id = GDMA_INVALID_PERIPH_TRIG; + return ESP_OK; +} + +esp_err_t gdma_get_free_m2m_trig_id_mask(gdma_channel_handle_t dma_chan, uint32_t *mask) +{ + gdma_pair_t *pair = NULL; + gdma_group_t *group = NULL; + ESP_RETURN_ON_FALSE(dma_chan && mask, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + + uint32_t free_mask = GDMA_LL_M2M_FREE_PERIPH_ID_MASK; pair = dma_chan->pair; group = pair->group; - dma_chan->periph_id = GDMA_INVALID_PERIPH_TRIG; - if (dma_chan->direction == GDMA_CHANNEL_DIRECTION_TX) { - gdma_ll_tx_connect_to_periph(group->hal.dev, pair->pair_id, GDMA_INVALID_PERIPH_TRIG); - } else { - gdma_ll_rx_connect_to_periph(group->hal.dev, pair->pair_id, GDMA_INVALID_PERIPH_TRIG); - } + portENTER_CRITICAL(&group->spinlock); + free_mask &= ~(group->tx_periph_in_use_mask); + free_mask &= ~(group->rx_periph_in_use_mask); + portEXIT_CRITICAL(&group->spinlock); -err: - return ret; + *mask = free_mask; + return ESP_OK; } esp_err_t gdma_set_transfer_ability(gdma_channel_handle_t dma_chan, const gdma_transfer_ability_t *ability) diff --git a/components/esp_hw_support/dma/gdma_priv.h b/components/esp_hw_support/dma/gdma_priv.h index 22c41b4c57..8dd70aa649 100644 --- a/components/esp_hw_support/dma/gdma_priv.h +++ b/components/esp_hw_support/dma/gdma_priv.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -43,6 +43,8 @@ typedef struct gdma_group_t { int group_id; // Group ID, index from 0 gdma_hal_context_t hal; // HAL instance is at group level portMUX_TYPE spinlock; // group level spinlock + uint32_t tx_periph_in_use_mask; // each bit indicates which peripheral (TX direction) has been occupied + uint32_t rx_periph_in_use_mask; // each bit indicates which peripheral (RX direction) has been occupied gdma_pair_t *pairs[SOC_GDMA_PAIRS_PER_GROUP]; // handles of GDMA pairs int pair_ref_counts[SOC_GDMA_PAIRS_PER_GROUP]; // reference count used to protect pair install/uninstall } gdma_group_t; diff --git a/components/esp_hw_support/include/esp_private/gdma.h b/components/esp_hw_support/include/esp_private/gdma.h index f3cce1d820..d71f3c6fc8 100644 --- a/components/esp_hw_support/include/esp_private/gdma.h +++ b/components/esp_hw_support/include/esp_private/gdma.h @@ -25,34 +25,6 @@ extern "C" { */ typedef struct gdma_channel_t *gdma_channel_handle_t; -/** - * @brief Enumeration of peripherals which have the DMA capability - * @note Some peripheral might not be available on certain chip, please refer to `soc_caps.h` for detail. - * - */ -typedef enum { - GDMA_TRIG_PERIPH_M2M, /*!< GDMA trigger peripheral: M2M */ - GDMA_TRIG_PERIPH_UHCI, /*!< GDMA trigger peripheral: UHCI */ - GDMA_TRIG_PERIPH_SPI, /*!< GDMA trigger peripheral: SPI */ - GDMA_TRIG_PERIPH_I2S, /*!< GDMA trigger peripheral: I2S */ - GDMA_TRIG_PERIPH_AES, /*!< GDMA trigger peripheral: AES */ - GDMA_TRIG_PERIPH_SHA, /*!< GDMA trigger peripheral: SHA */ - GDMA_TRIG_PERIPH_ADC, /*!< GDMA trigger peripheral: ADC */ - GDMA_TRIG_PERIPH_DAC, /*!< GDMA trigger peripheral: DAC */ - GDMA_TRIG_PERIPH_LCD, /*!< GDMA trigger peripheral: LCD */ - GDMA_TRIG_PERIPH_CAM, /*!< GDMA trigger peripheral: CAM */ - GDMA_TRIG_PERIPH_RMT, /*!< GDMA trigger peripheral: RMT */ -} gdma_trigger_peripheral_t; - -/** - * @brief Enumeration of GDMA channel direction - * - */ -typedef enum { - GDMA_CHANNEL_DIRECTION_TX, /*!< GDMA channel direction: TX */ - GDMA_CHANNEL_DIRECTION_RX, /*!< GDMA channel direction: RX */ -} gdma_channel_direction_t; - /** * @brief Collection of configuration items that used for allocating GDMA channel * @@ -373,6 +345,22 @@ typedef struct { */ 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); +/** + * @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); + #ifdef __cplusplus } #endif diff --git a/components/esp_hw_support/test_apps/dma/main/test_gdma.c b/components/esp_hw_support/test_apps/dma/main/test_gdma.c index 8d4e74fd6f..1c4fe18b2e 100644 --- a/components/esp_hw_support/test_apps/dma/main/test_gdma.c +++ b/components/esp_hw_support/test_apps/dma/main/test_gdma.c @@ -16,31 +16,27 @@ TEST_CASE("GDMA channel allocation", "[gdma]") gdma_tx_event_callbacks_t tx_cbs = {}; gdma_rx_event_callbacks_t rx_cbs = {}; - // install TX channels for different peripherals + // install TX channels for (int i = 0; i < SOC_GDMA_PAIRS_PER_GROUP; i++) { TEST_ESP_OK(gdma_new_channel(&channel_config, &tx_channels[i])); - TEST_ESP_OK(gdma_connect(tx_channels[i], GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_M2M, 0))); TEST_ESP_OK(gdma_register_tx_event_callbacks(tx_channels[i], &tx_cbs, NULL)); }; TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, gdma_new_channel(&channel_config, &tx_channels[0])); // Free interrupts before installing RX interrupts to ensure enough free interrupts for (int i = 0; i < SOC_GDMA_PAIRS_PER_GROUP; i++) { - TEST_ESP_OK(gdma_disconnect(tx_channels[i])); TEST_ESP_OK(gdma_del_channel(tx_channels[i])); } - // install RX channels for different peripherals + // install RX channels channel_config.direction = GDMA_CHANNEL_DIRECTION_RX; for (int i = 0; i < SOC_GDMA_PAIRS_PER_GROUP; i++) { TEST_ESP_OK(gdma_new_channel(&channel_config, &rx_channels[i])); - TEST_ESP_OK(gdma_connect(rx_channels[i], GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_M2M, 0))); TEST_ESP_OK(gdma_register_rx_event_callbacks(rx_channels[i], &rx_cbs, NULL)); } TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, gdma_new_channel(&channel_config, &rx_channels[0])); for (int i = 0; i < SOC_GDMA_PAIRS_PER_GROUP; i++) { - TEST_ESP_OK(gdma_disconnect(rx_channels[i])); TEST_ESP_OK(gdma_del_channel(rx_channels[i])); } @@ -61,7 +57,18 @@ TEST_CASE("GDMA channel allocation", "[gdma]") TEST_ESP_OK(gdma_new_channel(&channel_config, &rx_channels[1])); channel_config.sibling_chan = NULL; TEST_ESP_OK(gdma_new_channel(&channel_config, &rx_channels[0])); + + TEST_ESP_OK(gdma_connect(tx_channels[0], GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_SPI, 2))); + // can't connect multiple channels to the same peripheral + TEST_ESP_ERR(ESP_ERR_INVALID_STATE, gdma_connect(tx_channels[1], GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_SPI, 2))); + TEST_ESP_OK(gdma_connect(tx_channels[1], GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_M2M, 0))); + + TEST_ESP_OK(gdma_connect(rx_channels[0], GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_SPI, 2))); + // but rx and tx can connect to the same peripheral + TEST_ESP_OK(gdma_connect(rx_channels[1], GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_M2M, 0))); for (int i = 0; i < 2; i++) { + TEST_ESP_OK(gdma_disconnect(tx_channels[i])); + TEST_ESP_OK(gdma_disconnect(rx_channels[i])); TEST_ESP_OK(gdma_del_channel(tx_channels[i])); TEST_ESP_OK(gdma_del_channel(rx_channels[i])); } diff --git a/components/hal/esp32c2/include/hal/gdma_ll.h b/components/hal/esp32c2/include/hal/gdma_ll.h index 3db45a5f44..639309f972 100644 --- a/components/hal/esp32c2/include/hal/gdma_ll.h +++ b/components/hal/esp32c2/include/hal/gdma_ll.h @@ -8,6 +8,7 @@ #include /* Required for NULL constant */ #include #include +#include "hal/gdma_types.h" #include "soc/gdma_struct.h" #include "soc/gdma_reg.h" @@ -20,6 +21,10 @@ extern "C" { #define GDMA_LL_RX_EVENT_MASK (0x06A7) #define GDMA_LL_TX_EVENT_MASK (0x1958) +// any "valid" peripheral ID can be used for M2M mode +#define GDMA_LL_M2M_FREE_PERIPH_ID_MASK (0x185) +#define GDMA_LL_INVALID_PERIPH_ID (0x3F) + #define GDMA_LL_EVENT_TX_FIFO_UDF (1<<12) #define GDMA_LL_EVENT_TX_FIFO_OVF (1<<11) #define GDMA_LL_EVENT_RX_FIFO_UDF (1<<10) @@ -35,19 +40,6 @@ extern "C" { #define GDMA_LL_EVENT_RX_DONE (1<<0) ///////////////////////////////////// Common ///////////////////////////////////////// -/** - * @brief Enable DMA channel M2M mode (TX channel n forward data to RX channel n), disabled by default - */ -static inline void gdma_ll_enable_m2m_mode(gdma_dev_t *dev, uint32_t channel, bool enable) -{ - dev->channel[channel].in.in_conf0.mem_trans_en = enable; - if (enable) { - // to enable m2m mode, the tx chan has to be the same to rx chan, and set to a valid value - dev->channel[channel].in.in_peri_sel.sel = 0; - dev->channel[channel].out.out_peri_sel.sel = 0; - } -} - /** * @brief Enable DMA clock gating */ @@ -255,9 +247,19 @@ static inline void gdma_ll_rx_set_priority(gdma_dev_t *dev, uint32_t channel, ui /** * @brief Connect DMA RX channel to a given peripheral */ -static inline void gdma_ll_rx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, int periph_id) +static inline void gdma_ll_rx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, gdma_trigger_peripheral_t periph, int periph_id) { dev->channel[channel].in.in_peri_sel.sel = periph_id; + dev->channel[channel].in.in_conf0.mem_trans_en = (periph == GDMA_TRIG_PERIPH_M2M); +} + +/** + * @brief Disconnect DMA RX channel from peripheral + */ +static inline void gdma_ll_rx_disconnect_from_periph(gdma_dev_t *dev, uint32_t channel) +{ + dev->channel[channel].in.in_peri_sel.sel = GDMA_LL_INVALID_PERIPH_ID; + dev->channel[channel].in.in_conf0.mem_trans_en = false; } ///////////////////////////////////// TX ///////////////////////////////////////// @@ -458,11 +460,20 @@ static inline void gdma_ll_tx_set_priority(gdma_dev_t *dev, uint32_t channel, ui /** * @brief Connect DMA TX channel to a given peripheral */ -static inline void gdma_ll_tx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, int periph_id) +static inline void gdma_ll_tx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, gdma_trigger_peripheral_t periph, int periph_id) { + (void)periph; dev->channel[channel].out.out_peri_sel.sel = periph_id; } +/** + * @brief Disconnect DMA TX channel from peripheral + */ +static inline void gdma_ll_tx_disconnect_from_periph(gdma_dev_t *dev, uint32_t channel) +{ + dev->channel[channel].out.out_peri_sel.sel = GDMA_LL_INVALID_PERIPH_ID; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32c3/include/hal/gdma_ll.h b/components/hal/esp32c3/include/hal/gdma_ll.h index 67aa058e42..617b118f21 100644 --- a/components/hal/esp32c3/include/hal/gdma_ll.h +++ b/components/hal/esp32c3/include/hal/gdma_ll.h @@ -8,6 +8,7 @@ #include /* Required for NULL constant */ #include #include +#include "hal/gdma_types.h" #include "soc/gdma_struct.h" #include "soc/gdma_reg.h" @@ -20,6 +21,10 @@ extern "C" { #define GDMA_LL_RX_EVENT_MASK (0x06A7) #define GDMA_LL_TX_EVENT_MASK (0x1958) +// any "valid" peripheral ID can be used for M2M mode +#define GDMA_LL_M2M_FREE_PERIPH_ID_MASK (0x1CD) +#define GDMA_LL_INVALID_PERIPH_ID (0x3F) + #define GDMA_LL_EVENT_TX_FIFO_UDF (1<<12) #define GDMA_LL_EVENT_TX_FIFO_OVF (1<<11) #define GDMA_LL_EVENT_RX_FIFO_UDF (1<<10) @@ -35,19 +40,6 @@ extern "C" { #define GDMA_LL_EVENT_RX_DONE (1<<0) ///////////////////////////////////// Common ///////////////////////////////////////// -/** - * @brief Enable DMA channel M2M mode (TX channel n forward data to RX channel n), disabled by default - */ -static inline void gdma_ll_enable_m2m_mode(gdma_dev_t *dev, uint32_t channel, bool enable) -{ - dev->channel[channel].in.in_conf0.mem_trans_en = enable; - if (enable) { - // to enable m2m mode, the tx chan has to be the same to rx chan, and set to a valid value - dev->channel[channel].in.in_peri_sel.sel = 0; - dev->channel[channel].out.out_peri_sel.sel = 0; - } -} - /** * @brief Enable DMA clock gating */ @@ -255,9 +247,19 @@ static inline void gdma_ll_rx_set_priority(gdma_dev_t *dev, uint32_t channel, ui /** * @brief Connect DMA RX channel to a given peripheral */ -static inline void gdma_ll_rx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, int periph_id) +static inline void gdma_ll_rx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, gdma_trigger_peripheral_t periph, int periph_id) { dev->channel[channel].in.in_peri_sel.sel = periph_id; + dev->channel[channel].in.in_conf0.mem_trans_en = (periph == GDMA_TRIG_PERIPH_M2M); +} + +/** + * @brief Disconnect DMA RX channel from peripheral + */ +static inline void gdma_ll_rx_disconnect_from_periph(gdma_dev_t *dev, uint32_t channel) +{ + dev->channel[channel].in.in_peri_sel.sel = GDMA_LL_INVALID_PERIPH_ID; + dev->channel[channel].in.in_conf0.mem_trans_en = false; } ///////////////////////////////////// TX ///////////////////////////////////////// @@ -458,11 +460,20 @@ static inline void gdma_ll_tx_set_priority(gdma_dev_t *dev, uint32_t channel, ui /** * @brief Connect DMA TX channel to a given peripheral */ -static inline void gdma_ll_tx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, int periph_id) +static inline void gdma_ll_tx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, gdma_trigger_peripheral_t periph, int periph_id) { + (void)periph; dev->channel[channel].out.out_peri_sel.sel = periph_id; } +/** + * @brief Disconnect DMA TX channel from peripheral + */ +static inline void gdma_ll_tx_disconnect_from_periph(gdma_dev_t *dev, uint32_t channel) +{ + dev->channel[channel].out.out_peri_sel.sel = GDMA_LL_INVALID_PERIPH_ID; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32c6/include/hal/apm_ll.h b/components/hal/esp32c6/include/hal/apm_ll.h index 555aa3d290..22ef51f4bd 100644 --- a/components/hal/esp32c6/include/hal/apm_ll.h +++ b/components/hal/esp32c6/include/hal/apm_ll.h @@ -26,8 +26,8 @@ typedef enum { APM_LL_MASTER_MODEM = 4, APM_LL_MASTER_MEM_MONITOR = 5, APM_LL_MASTER_TRACE = 6, + APM_LL_MASTER_GDMA = 16, // The beginning of GDMA master ID APM_LL_MASTER_GDMA_SPI2 = 16, - APM_LL_MASTER_GDMA_M2M = 17, // a dummy GDMA trigger, used by M2M copy APM_LL_MASTER_GDMA_UHCI0 = 18, APM_LL_MASTER_GDMA_I2S0 = 19, APM_LL_MASTER_GDMA_AES = 22, diff --git a/components/hal/esp32c6/include/hal/gdma_ll.h b/components/hal/esp32c6/include/hal/gdma_ll.h index 254bfbdd15..21c55bfdad 100644 --- a/components/hal/esp32c6/include/hal/gdma_ll.h +++ b/components/hal/esp32c6/include/hal/gdma_ll.h @@ -12,7 +12,6 @@ #include "soc/gdma_struct.h" #include "soc/gdma_reg.h" #include "soc/soc_etm_source.h" -#include "soc/gdma_channel.h" #ifdef __cplusplus extern "C" { @@ -23,6 +22,10 @@ extern "C" { #define GDMA_LL_RX_EVENT_MASK (0x7F) #define GDMA_LL_TX_EVENT_MASK (0x3F) +// any "dummy" peripheral ID can be used for M2M mode +#define GDMA_LL_M2M_FREE_PERIPH_ID_MASK (0xFC32) +#define GDMA_LL_INVALID_PERIPH_ID (0x3F) + #define GDMA_LL_EVENT_TX_FIFO_UDF (1<<5) #define GDMA_LL_EVENT_TX_FIFO_OVF (1<<4) #define GDMA_LL_EVENT_RX_FIFO_UDF (1<<6) @@ -82,19 +85,6 @@ extern "C" { }}}[group][chan][task] ///////////////////////////////////// Common ///////////////////////////////////////// -/** - * @brief Enable DMA channel M2M mode (TX channel n forward data to RX channel n), disabled by default - */ -static inline void gdma_ll_enable_m2m_mode(gdma_dev_t *dev, uint32_t channel, bool enable) -{ - dev->channel[channel].in.in_conf0.mem_trans_en = enable; - if (enable) { - // to enable m2m mode, the tx chan has to be the same to rx chan, and set to a dummy value - dev->channel[channel].in.in_peri_sel.peri_in_sel = SOC_GDMA_TRIG_PERIPH_M2M0; - dev->channel[channel].out.out_peri_sel.peri_out_sel = SOC_GDMA_TRIG_PERIPH_M2M0; - } -} - /** * @brief Enable DMA clock gating */ @@ -302,9 +292,19 @@ static inline void gdma_ll_rx_set_priority(gdma_dev_t *dev, uint32_t channel, ui /** * @brief Connect DMA RX channel to a given peripheral */ -static inline void gdma_ll_rx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, int periph_id) +static inline void gdma_ll_rx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, gdma_trigger_peripheral_t periph, int periph_id) { dev->channel[channel].in.in_peri_sel.peri_in_sel = periph_id; + dev->channel[channel].in.in_conf0.mem_trans_en = (periph == GDMA_TRIG_PERIPH_M2M); +} + +/** + * @brief Disconnect DMA RX channel from peripheral + */ +static inline void gdma_ll_rx_disconnect_from_periph(gdma_dev_t *dev, uint32_t channel) +{ + dev->channel[channel].in.in_peri_sel.peri_in_sel = GDMA_LL_INVALID_PERIPH_ID; + dev->channel[channel].in.in_conf0.mem_trans_en = false; } /** @@ -515,11 +515,20 @@ static inline void gdma_ll_tx_set_priority(gdma_dev_t *dev, uint32_t channel, ui /** * @brief Connect DMA TX channel to a given peripheral */ -static inline void gdma_ll_tx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, int periph_id) +static inline void gdma_ll_tx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, gdma_trigger_peripheral_t periph, int periph_id) { + (void)periph; dev->channel[channel].out.out_peri_sel.peri_out_sel = periph_id; } +/** + * @brief Disconnect DMA TX channel from peripheral + */ +static inline void gdma_ll_tx_disconnect_from_periph(gdma_dev_t *dev, uint32_t channel) +{ + dev->channel[channel].out.out_peri_sel.peri_out_sel = GDMA_LL_INVALID_PERIPH_ID; +} + /** * @brief Whether to enable the ETM subsystem for TX channel * diff --git a/components/hal/esp32h2/include/hal/apm_ll.h b/components/hal/esp32h2/include/hal/apm_ll.h index 555aa3d290..22ef51f4bd 100644 --- a/components/hal/esp32h2/include/hal/apm_ll.h +++ b/components/hal/esp32h2/include/hal/apm_ll.h @@ -26,8 +26,8 @@ typedef enum { APM_LL_MASTER_MODEM = 4, APM_LL_MASTER_MEM_MONITOR = 5, APM_LL_MASTER_TRACE = 6, + APM_LL_MASTER_GDMA = 16, // The beginning of GDMA master ID APM_LL_MASTER_GDMA_SPI2 = 16, - APM_LL_MASTER_GDMA_M2M = 17, // a dummy GDMA trigger, used by M2M copy APM_LL_MASTER_GDMA_UHCI0 = 18, APM_LL_MASTER_GDMA_I2S0 = 19, APM_LL_MASTER_GDMA_AES = 22, diff --git a/components/hal/esp32h2/include/hal/gdma_ll.h b/components/hal/esp32h2/include/hal/gdma_ll.h index 254bfbdd15..21c55bfdad 100644 --- a/components/hal/esp32h2/include/hal/gdma_ll.h +++ b/components/hal/esp32h2/include/hal/gdma_ll.h @@ -12,7 +12,6 @@ #include "soc/gdma_struct.h" #include "soc/gdma_reg.h" #include "soc/soc_etm_source.h" -#include "soc/gdma_channel.h" #ifdef __cplusplus extern "C" { @@ -23,6 +22,10 @@ extern "C" { #define GDMA_LL_RX_EVENT_MASK (0x7F) #define GDMA_LL_TX_EVENT_MASK (0x3F) +// any "dummy" peripheral ID can be used for M2M mode +#define GDMA_LL_M2M_FREE_PERIPH_ID_MASK (0xFC32) +#define GDMA_LL_INVALID_PERIPH_ID (0x3F) + #define GDMA_LL_EVENT_TX_FIFO_UDF (1<<5) #define GDMA_LL_EVENT_TX_FIFO_OVF (1<<4) #define GDMA_LL_EVENT_RX_FIFO_UDF (1<<6) @@ -82,19 +85,6 @@ extern "C" { }}}[group][chan][task] ///////////////////////////////////// Common ///////////////////////////////////////// -/** - * @brief Enable DMA channel M2M mode (TX channel n forward data to RX channel n), disabled by default - */ -static inline void gdma_ll_enable_m2m_mode(gdma_dev_t *dev, uint32_t channel, bool enable) -{ - dev->channel[channel].in.in_conf0.mem_trans_en = enable; - if (enable) { - // to enable m2m mode, the tx chan has to be the same to rx chan, and set to a dummy value - dev->channel[channel].in.in_peri_sel.peri_in_sel = SOC_GDMA_TRIG_PERIPH_M2M0; - dev->channel[channel].out.out_peri_sel.peri_out_sel = SOC_GDMA_TRIG_PERIPH_M2M0; - } -} - /** * @brief Enable DMA clock gating */ @@ -302,9 +292,19 @@ static inline void gdma_ll_rx_set_priority(gdma_dev_t *dev, uint32_t channel, ui /** * @brief Connect DMA RX channel to a given peripheral */ -static inline void gdma_ll_rx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, int periph_id) +static inline void gdma_ll_rx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, gdma_trigger_peripheral_t periph, int periph_id) { dev->channel[channel].in.in_peri_sel.peri_in_sel = periph_id; + dev->channel[channel].in.in_conf0.mem_trans_en = (periph == GDMA_TRIG_PERIPH_M2M); +} + +/** + * @brief Disconnect DMA RX channel from peripheral + */ +static inline void gdma_ll_rx_disconnect_from_periph(gdma_dev_t *dev, uint32_t channel) +{ + dev->channel[channel].in.in_peri_sel.peri_in_sel = GDMA_LL_INVALID_PERIPH_ID; + dev->channel[channel].in.in_conf0.mem_trans_en = false; } /** @@ -515,11 +515,20 @@ static inline void gdma_ll_tx_set_priority(gdma_dev_t *dev, uint32_t channel, ui /** * @brief Connect DMA TX channel to a given peripheral */ -static inline void gdma_ll_tx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, int periph_id) +static inline void gdma_ll_tx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, gdma_trigger_peripheral_t periph, int periph_id) { + (void)periph; dev->channel[channel].out.out_peri_sel.peri_out_sel = periph_id; } +/** + * @brief Disconnect DMA TX channel from peripheral + */ +static inline void gdma_ll_tx_disconnect_from_periph(gdma_dev_t *dev, uint32_t channel) +{ + dev->channel[channel].out.out_peri_sel.peri_out_sel = GDMA_LL_INVALID_PERIPH_ID; +} + /** * @brief Whether to enable the ETM subsystem for TX channel * diff --git a/components/hal/esp32h4/include/hal/gdma_ll.h b/components/hal/esp32h4/include/hal/gdma_ll.h index 67aa058e42..617b118f21 100644 --- a/components/hal/esp32h4/include/hal/gdma_ll.h +++ b/components/hal/esp32h4/include/hal/gdma_ll.h @@ -8,6 +8,7 @@ #include /* Required for NULL constant */ #include #include +#include "hal/gdma_types.h" #include "soc/gdma_struct.h" #include "soc/gdma_reg.h" @@ -20,6 +21,10 @@ extern "C" { #define GDMA_LL_RX_EVENT_MASK (0x06A7) #define GDMA_LL_TX_EVENT_MASK (0x1958) +// any "valid" peripheral ID can be used for M2M mode +#define GDMA_LL_M2M_FREE_PERIPH_ID_MASK (0x1CD) +#define GDMA_LL_INVALID_PERIPH_ID (0x3F) + #define GDMA_LL_EVENT_TX_FIFO_UDF (1<<12) #define GDMA_LL_EVENT_TX_FIFO_OVF (1<<11) #define GDMA_LL_EVENT_RX_FIFO_UDF (1<<10) @@ -35,19 +40,6 @@ extern "C" { #define GDMA_LL_EVENT_RX_DONE (1<<0) ///////////////////////////////////// Common ///////////////////////////////////////// -/** - * @brief Enable DMA channel M2M mode (TX channel n forward data to RX channel n), disabled by default - */ -static inline void gdma_ll_enable_m2m_mode(gdma_dev_t *dev, uint32_t channel, bool enable) -{ - dev->channel[channel].in.in_conf0.mem_trans_en = enable; - if (enable) { - // to enable m2m mode, the tx chan has to be the same to rx chan, and set to a valid value - dev->channel[channel].in.in_peri_sel.sel = 0; - dev->channel[channel].out.out_peri_sel.sel = 0; - } -} - /** * @brief Enable DMA clock gating */ @@ -255,9 +247,19 @@ static inline void gdma_ll_rx_set_priority(gdma_dev_t *dev, uint32_t channel, ui /** * @brief Connect DMA RX channel to a given peripheral */ -static inline void gdma_ll_rx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, int periph_id) +static inline void gdma_ll_rx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, gdma_trigger_peripheral_t periph, int periph_id) { dev->channel[channel].in.in_peri_sel.sel = periph_id; + dev->channel[channel].in.in_conf0.mem_trans_en = (periph == GDMA_TRIG_PERIPH_M2M); +} + +/** + * @brief Disconnect DMA RX channel from peripheral + */ +static inline void gdma_ll_rx_disconnect_from_periph(gdma_dev_t *dev, uint32_t channel) +{ + dev->channel[channel].in.in_peri_sel.sel = GDMA_LL_INVALID_PERIPH_ID; + dev->channel[channel].in.in_conf0.mem_trans_en = false; } ///////////////////////////////////// TX ///////////////////////////////////////// @@ -458,11 +460,20 @@ static inline void gdma_ll_tx_set_priority(gdma_dev_t *dev, uint32_t channel, ui /** * @brief Connect DMA TX channel to a given peripheral */ -static inline void gdma_ll_tx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, int periph_id) +static inline void gdma_ll_tx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, gdma_trigger_peripheral_t periph, int periph_id) { + (void)periph; dev->channel[channel].out.out_peri_sel.sel = periph_id; } +/** + * @brief Disconnect DMA TX channel from peripheral + */ +static inline void gdma_ll_tx_disconnect_from_periph(gdma_dev_t *dev, uint32_t channel) +{ + dev->channel[channel].out.out_peri_sel.sel = GDMA_LL_INVALID_PERIPH_ID; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32s3/include/hal/gdma_ll.h b/components/hal/esp32s3/include/hal/gdma_ll.h index de8337468d..2fc7029303 100644 --- a/components/hal/esp32s3/include/hal/gdma_ll.h +++ b/components/hal/esp32s3/include/hal/gdma_ll.h @@ -8,7 +8,7 @@ #include /* For NULL declaration */ #include #include -#include "soc/soc_caps.h" +#include "hal/gdma_types.h" #include "soc/gdma_struct.h" #include "soc/gdma_reg.h" @@ -21,6 +21,10 @@ extern "C" { #define GDMA_LL_RX_EVENT_MASK (0x3FF) #define GDMA_LL_TX_EVENT_MASK (0xFF) +// any "valid" peripheral ID can be used for M2M mode +#define GDMA_LL_M2M_FREE_PERIPH_ID_MASK (0x3FF) +#define GDMA_LL_INVALID_PERIPH_ID (0x3F) + #define GDMA_LL_EVENT_TX_L3_FIFO_UDF (1<<7) #define GDMA_LL_EVENT_TX_L3_FIFO_OVF (1<<6) #define GDMA_LL_EVENT_TX_L1_FIFO_UDF (1<<5) @@ -49,19 +53,6 @@ extern "C" { #define GDMA_LL_EXT_MEM_BK_SIZE_64B (2) ///////////////////////////////////// Common ///////////////////////////////////////// -/** - * @brief Enable DMA channel M2M mode (TX channel n forward data to RX channel n), disabled by default - */ -static inline void gdma_ll_enable_m2m_mode(gdma_dev_t *dev, uint32_t channel, bool enable) -{ - dev->channel[channel].in.conf0.mem_trans_en = enable; - if (enable) { - // to enable m2m mode, the tx chan has to be the same to rx chan, and set to a valid value - dev->channel[channel].in.peri_sel.sel = 0; - dev->channel[channel].out.peri_sel.sel = 0; - } -} - /** * @brief Enable DMA clock gating */ @@ -303,9 +294,19 @@ static inline void gdma_ll_rx_set_priority(gdma_dev_t *dev, uint32_t channel, ui /** * @brief Connect DMA RX channel to a given peripheral */ -static inline void gdma_ll_rx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, int periph_id) +static inline void gdma_ll_rx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, gdma_trigger_peripheral_t periph, int periph_id) { dev->channel[channel].in.peri_sel.sel = periph_id; + dev->channel[channel].in.conf0.mem_trans_en = (periph == GDMA_TRIG_PERIPH_M2M); +} + +/** + * @brief Disconnect DMA RX channel from peripheral + */ +static inline void gdma_ll_rx_disconnect_from_periph(gdma_dev_t *dev, uint32_t channel) +{ + dev->channel[channel].in.peri_sel.sel = GDMA_LL_INVALID_PERIPH_ID; + dev->channel[channel].in.conf0.mem_trans_en = false; } ///////////////////////////////////// TX ///////////////////////////////////////// @@ -532,11 +533,20 @@ static inline void gdma_ll_tx_set_priority(gdma_dev_t *dev, uint32_t channel, ui /** * @brief Connect DMA TX channel to a given peripheral */ -static inline void gdma_ll_tx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, int periph_id) +static inline void gdma_ll_tx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, gdma_trigger_peripheral_t periph, int periph_id) { + (void)periph; dev->channel[channel].out.peri_sel.sel = periph_id; } +/** + * @brief Disconnect DMA TX channel from peripheral + */ +static inline void gdma_ll_tx_disconnect_from_periph(gdma_dev_t *dev, uint32_t channel) +{ + dev->channel[channel].out.peri_sel.sel = GDMA_LL_INVALID_PERIPH_ID; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/include/hal/gdma_types.h b/components/hal/include/hal/gdma_types.h index cd3c9f39c5..1f2027bdab 100644 --- a/components/hal/include/hal/gdma_types.h +++ b/components/hal/include/hal/gdma_types.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,6 +10,34 @@ extern "C" { #endif +/** + * @brief Enumeration of peripherals which have the DMA capability + * @note Some peripheral might not be available on certain chip, please refer to `soc_caps.h` for detail. + * + */ +typedef enum { + GDMA_TRIG_PERIPH_M2M, /*!< GDMA trigger peripheral: M2M */ + GDMA_TRIG_PERIPH_UHCI, /*!< GDMA trigger peripheral: UHCI */ + GDMA_TRIG_PERIPH_SPI, /*!< GDMA trigger peripheral: SPI */ + GDMA_TRIG_PERIPH_I2S, /*!< GDMA trigger peripheral: I2S */ + GDMA_TRIG_PERIPH_AES, /*!< GDMA trigger peripheral: AES */ + GDMA_TRIG_PERIPH_SHA, /*!< GDMA trigger peripheral: SHA */ + GDMA_TRIG_PERIPH_ADC, /*!< GDMA trigger peripheral: ADC */ + GDMA_TRIG_PERIPH_DAC, /*!< GDMA trigger peripheral: DAC */ + GDMA_TRIG_PERIPH_LCD, /*!< GDMA trigger peripheral: LCD */ + GDMA_TRIG_PERIPH_CAM, /*!< GDMA trigger peripheral: CAM */ + GDMA_TRIG_PERIPH_RMT, /*!< GDMA trigger peripheral: RMT */ +} gdma_trigger_peripheral_t; + +/** + * @brief Enumeration of GDMA channel direction + * + */ +typedef enum { + GDMA_CHANNEL_DIRECTION_TX, /*!< GDMA channel direction: TX */ + GDMA_CHANNEL_DIRECTION_RX, /*!< GDMA channel direction: RX */ +} gdma_channel_direction_t; + /** * @brief GDMA channel events that supported by the ETM module */ diff --git a/components/soc/esp32c6/include/soc/gdma_channel.h b/components/soc/esp32c6/include/soc/gdma_channel.h index 6025fcd94a..785d920785 100644 --- a/components/soc/esp32c6/include/soc/gdma_channel.h +++ b/components/soc/esp32c6/include/soc/gdma_channel.h @@ -7,8 +7,8 @@ #pragma once // The following macros have a format SOC_[periph][instance_id] to make it work with `GDMA_MAKE_TRIGGER` +#define SOC_GDMA_TRIG_PERIPH_M2M0 (-1) #define SOC_GDMA_TRIG_PERIPH_SPI2 (0) -#define SOC_GDMA_TRIG_PERIPH_M2M0 (1) #define SOC_GDMA_TRIG_PERIPH_UHCI0 (2) #define SOC_GDMA_TRIG_PERIPH_I2S0 (3) #define SOC_GDMA_TRIG_PERIPH_AES0 (6) diff --git a/components/soc/esp32h2/include/soc/gdma_channel.h b/components/soc/esp32h2/include/soc/gdma_channel.h index 6025fcd94a..785d920785 100644 --- a/components/soc/esp32h2/include/soc/gdma_channel.h +++ b/components/soc/esp32h2/include/soc/gdma_channel.h @@ -7,8 +7,8 @@ #pragma once // The following macros have a format SOC_[periph][instance_id] to make it work with `GDMA_MAKE_TRIGGER` +#define SOC_GDMA_TRIG_PERIPH_M2M0 (-1) #define SOC_GDMA_TRIG_PERIPH_SPI2 (0) -#define SOC_GDMA_TRIG_PERIPH_M2M0 (1) #define SOC_GDMA_TRIG_PERIPH_UHCI0 (2) #define SOC_GDMA_TRIG_PERIPH_I2S0 (3) #define SOC_GDMA_TRIG_PERIPH_AES0 (6)