From 8506035f5a6498258e3095fac5983fb8643ca911 Mon Sep 17 00:00:00 2001 From: morris Date: Thu, 8 Jan 2026 18:25:42 +0800 Subject: [PATCH] refactor(gdma): enhance M2M capability handling --- .../esp_driver_spi/src/gpspi/spi_common.c | 2 -- components/esp_hw_support/dma/gdma.c | 34 ++++++++++++------- components/hal/esp32c2/include/hal/gdma_ll.h | 2 ++ components/hal/esp32c3/include/hal/gdma_ll.h | 2 ++ .../hal/esp32c5/include/hal/ahb_dma_ll.h | 2 ++ components/hal/esp32c6/include/hal/gdma_ll.h | 2 ++ .../hal/esp32c61/include/hal/ahb_dma_ll.h | 2 ++ components/hal/esp32h2/include/hal/gdma_ll.h | 2 ++ components/hal/esp32h21/include/hal/gdma_ll.h | 2 ++ .../hal/esp32h4/include/hal/ahb_dma_ll.h | 2 ++ components/hal/esp32p4/include/hal/gdma_ll.h | 8 +++++ components/hal/esp32s3/include/hal/gdma_ll.h | 2 ++ 12 files changed, 48 insertions(+), 14 deletions(-) diff --git a/components/esp_driver_spi/src/gpspi/spi_common.c b/components/esp_driver_spi/src/gpspi/spi_common.c index 98da337c77..d55703fa1c 100644 --- a/components/esp_driver_spi/src/gpspi/spi_common.c +++ b/components/esp_driver_spi/src/gpspi/spi_common.c @@ -227,7 +227,6 @@ static esp_err_t alloc_dma_chan(spi_host_device_t host_id, spi_dma_chan_t dma_ch if (dma_chan == SPI_DMA_CH_AUTO) { gdma_channel_alloc_config_t tx_alloc_config = { - .flags.reserve_sibling = 1, #if CONFIG_SPI_MASTER_ISR_IN_IRAM .flags.isr_cache_safe = true, #endif @@ -237,7 +236,6 @@ static esp_err_t alloc_dma_chan(spi_host_device_t host_id, spi_dma_chan_t dma_ch gdma_channel_alloc_config_t rx_alloc_config = { .direction = GDMA_CHANNEL_DIRECTION_RX, - .sibling_chan = dma_ctx->tx_dma_chan, #if CONFIG_SPI_MASTER_ISR_IN_IRAM .flags.isr_cache_safe = true, #endif diff --git a/components/esp_hw_support/dma/gdma.c b/components/esp_hw_support/dma/gdma.c index 29211df99e..a1348db51c 100644 --- a/components/esp_hw_support/dma/gdma.c +++ b/components/esp_hw_support/dma/gdma.c @@ -11,7 +11,7 @@ * +-----------------------------------+--+ +--+-----------------------------------+ * | GDMA-Group-X | | | | GDMA-Group-Y | * | +-------------+ +------------+ | | | | +-------------+ +------------+ | - * | | GDMA-Pair-0 |... |GDMA-Pair-N | | | | | | GDMA-Pair-0 |... |GDMA-Pair-N | | + * | | GDMA-Pair-0 |... |GDMA-Pair-N | | | | | | GDMA-Pair-0 |... |GDMA-Pair-M | | * | | | | | | | | | | | | | | * | | TX-Chan |... | TX-Chan | | | | | | TX-Chan |... | TX-Chan | | * | | RX-Chan | | RX-Chan | | | | | | RX-Chan | | RX-Chan | | @@ -70,6 +70,7 @@ typedef struct { int start_group_id; int end_group_id; int pairs_per_group; + uint32_t m2m_capable_mask; void (*hal_init)(gdma_hal_context_t *hal, const gdma_hal_config_t *config); } gdma_channel_search_info_t; @@ -116,6 +117,13 @@ static esp_err_t do_allocate_gdma_channel(const gdma_channel_search_info_t *sear ESP_GOTO_ON_FALSE(group, ESP_ERR_NO_MEM, err, TAG, "no mem for group(%d)", i); group->bus_id = search_info->bus_id; for (int j = 0; j < pairs_per_group && search_code; j++) { // loop to search pair + // Check M2M capability BEFORE acquiring pair to avoid unnecessary allocation + if (config->flags.reserve_sibling) { // Both channels requested (implicit M2M usage) + if (!((1 << j) & search_info->m2m_capable_mask)) { + ESP_LOGV(TAG, "pair(%d,%d) not M2M capable, skip", i, j); + continue; // Skip pairs that don't support M2M + } + } pair = gdma_acquire_pair_handle(group, j); ESP_GOTO_ON_FALSE(pair, ESP_ERR_NO_MEM, err, TAG, "no mem for pair(%d,%d)", i, j); portENTER_CRITICAL(&pair->spinlock); @@ -175,7 +183,7 @@ search_done: } (*ret_chan)->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED; - ESP_LOGD(TAG, "new %s channel (%d,%d) at %p", (config->direction == GDMA_CHANNEL_DIRECTION_TX) ? "tx" : "rx", + ESP_LOGV(TAG, "new %s channel (%d,%d) at %p", (config->direction == GDMA_CHANNEL_DIRECTION_TX) ? "tx" : "rx", group->group_id, pair->pair_id, *ret_chan); return ESP_OK; @@ -203,6 +211,7 @@ esp_err_t gdma_new_ahb_channel(const gdma_channel_alloc_config_t *config, gdma_c .start_group_id = GDMA_LL_AHB_GROUP_START_ID, .end_group_id = GDMA_LL_AHB_GROUP_START_ID + GDMA_LL_AHB_NUM_GROUPS, .pairs_per_group = GDMA_LL_AHB_PAIRS_PER_GROUP, + .m2m_capable_mask = GDMA_LL_AHB_M2M_CAPABLE_PAIR_MASK, .hal_init = gdma_ahb_hal_init, }; return do_allocate_gdma_channel(&search_info, config, ret_chan); @@ -217,6 +226,7 @@ esp_err_t gdma_new_axi_channel(const gdma_channel_alloc_config_t *config, gdma_c .start_group_id = GDMA_LL_AXI_GROUP_START_ID, .end_group_id = GDMA_LL_AXI_GROUP_START_ID + GDMA_LL_AXI_NUM_GROUPS, .pairs_per_group = GDMA_LL_AXI_PAIRS_PER_GROUP, + .m2m_capable_mask = GDMA_LL_AXI_M2M_CAPABLE_PAIR_MASK, .hal_init = gdma_axi_hal_init, }; return do_allocate_gdma_channel(&search_info, config, ret_chan); @@ -607,7 +617,7 @@ static void gdma_release_group_handle(gdma_group_t *group) gdma_ll_enable_bus_clock(group_id, false); } free(group); - ESP_LOGD(TAG, "del group %d", group_id); + ESP_LOGV(TAG, "del group %d", group_id); } } @@ -644,7 +654,7 @@ static gdma_group_t *gdma_acquire_group_handle(int group_id, void (*hal_init)(gd .group_id = group_id, }; hal_init(&group->hal, &config); - ESP_LOGD(TAG, "new group (%d) at %p", group_id, group); + ESP_LOGV(TAG, "new group (%d) at %p", group_id, group); } else { free(pre_alloc_group); } @@ -672,7 +682,7 @@ static void gdma_release_pair_handle(gdma_pair_t *pair) #if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_GDMA_SUPPORT_SLEEP_RETENTION gdma_sleep_retention_deinit(group->group_id, pair_id); #endif - ESP_LOGD(TAG, "del pair (%d,%d)", group->group_id, pair_id); + ESP_LOGV(TAG, "del pair (%d,%d)", group->group_id, pair_id); gdma_release_group_handle(group); } } @@ -712,7 +722,7 @@ static gdma_pair_t *gdma_acquire_pair_handle(gdma_group_t *group, int pair_id) #if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_GDMA_SUPPORT_SLEEP_RETENTION gdma_sleep_retention_init(group->group_id, pair_id); #endif - ESP_LOGD(TAG, "new pair (%d,%d) at %p", group->group_id, pair_id, pair); + ESP_LOGV(TAG, "new pair (%d,%d) at %p", group->group_id, pair_id, pair); } else { free(pre_alloc_pair); } @@ -739,11 +749,11 @@ static esp_err_t gdma_del_tx_channel(gdma_channel_t *dma_channel) gdma_hal_enable_intr(hal, pair_id, GDMA_CHANNEL_DIRECTION_TX, UINT32_MAX, false); // disable all interrupt events gdma_hal_clear_intr(hal, pair->pair_id, GDMA_CHANNEL_DIRECTION_TX, UINT32_MAX); // clear all pending events portEXIT_CRITICAL(&pair->spinlock); - ESP_LOGD(TAG, "uninstall interrupt service for tx channel (%d,%d)", group_id, pair_id); + ESP_LOGV(TAG, "uninstall interrupt service for tx channel (%d,%d)", group_id, pair_id); } free(tx_chan); - ESP_LOGD(TAG, "del tx channel (%d,%d)", group_id, pair_id); + ESP_LOGV(TAG, "del tx channel (%d,%d)", group_id, pair_id); // channel has a reference on pair, release it now gdma_release_pair_handle(pair); return ESP_OK; @@ -768,11 +778,11 @@ static esp_err_t gdma_del_rx_channel(gdma_channel_t *dma_channel) gdma_hal_enable_intr(hal, pair_id, GDMA_CHANNEL_DIRECTION_RX, UINT32_MAX, false); // disable all interrupt events gdma_hal_clear_intr(hal, pair->pair_id, GDMA_CHANNEL_DIRECTION_RX, UINT32_MAX); // clear all pending events portEXIT_CRITICAL(&pair->spinlock); - ESP_LOGD(TAG, "uninstall interrupt service for rx channel (%d,%d)", group_id, pair_id); + ESP_LOGV(TAG, "uninstall interrupt service for rx channel (%d,%d)", group_id, pair_id); } free(rx_chan); - ESP_LOGD(TAG, "del rx channel (%d,%d)", group_id, pair_id); + ESP_LOGV(TAG, "del rx channel (%d,%d)", group_id, pair_id); gdma_release_pair_handle(pair); return ESP_OK; } @@ -884,7 +894,7 @@ static esp_err_t gdma_install_rx_interrupt(gdma_rx_channel_t *rx_chan) gdma_hal_enable_intr(hal, pair_id, GDMA_CHANNEL_DIRECTION_RX, UINT32_MAX, false); // disable all interrupt events gdma_hal_clear_intr(hal, pair_id, GDMA_CHANNEL_DIRECTION_RX, UINT32_MAX); // clear all pending events portEXIT_CRITICAL(&pair->spinlock); - ESP_LOGD(TAG, "install interrupt service for rx channel (%d,%d)", group->group_id, pair_id); + ESP_LOGV(TAG, "install interrupt service for rx channel (%d,%d)", group->group_id, pair_id); err: return ret; @@ -916,7 +926,7 @@ static esp_err_t gdma_install_tx_interrupt(gdma_tx_channel_t *tx_chan) gdma_hal_enable_intr(hal, pair_id, GDMA_CHANNEL_DIRECTION_TX, UINT32_MAX, false); // disable all interrupt events gdma_hal_clear_intr(hal, pair_id, GDMA_CHANNEL_DIRECTION_TX, UINT32_MAX); // clear all pending events portEXIT_CRITICAL(&pair->spinlock); - ESP_LOGD(TAG, "install interrupt service for tx channel (%d,%d)", group->group_id, pair_id); + ESP_LOGV(TAG, "install interrupt service for tx channel (%d,%d)", group->group_id, pair_id); err: return ret; diff --git a/components/hal/esp32c2/include/hal/gdma_ll.h b/components/hal/esp32c2/include/hal/gdma_ll.h index ee877d5b3e..ff327126de 100644 --- a/components/hal/esp32c2/include/hal/gdma_ll.h +++ b/components/hal/esp32c2/include/hal/gdma_ll.h @@ -47,6 +47,8 @@ extern "C" { #define GDMA_LL_AHB_PAIRS_PER_GROUP 1 // Number of GDMA pairs in each AHB group #define GDMA_LL_AHB_TX_RX_SHARE_INTERRUPT 1 // TX and RX channel in the same pair will share the same interrupt source number +#define GDMA_LL_AHB_M2M_CAPABLE_PAIR_MASK 0x01 // pair 0 is M2M capable + #define GDMA_LL_AHB_DESC_ALIGNMENT 4 #define GDMA_LL_AHB_RX_BURST_NEEDS_ALIGNMENT 1 diff --git a/components/hal/esp32c3/include/hal/gdma_ll.h b/components/hal/esp32c3/include/hal/gdma_ll.h index f7b3147e4d..511d692613 100644 --- a/components/hal/esp32c3/include/hal/gdma_ll.h +++ b/components/hal/esp32c3/include/hal/gdma_ll.h @@ -47,6 +47,8 @@ extern "C" { #define GDMA_LL_AHB_PAIRS_PER_GROUP 3 // Number of GDMA pairs in each AHB group #define GDMA_LL_AHB_TX_RX_SHARE_INTERRUPT 1 // TX and RX channel in the same pair will share the same interrupt source number +#define GDMA_LL_AHB_M2M_CAPABLE_PAIR_MASK 0x07 // pair 0,1,2 are M2M capable + #define GDMA_LL_AHB_DESC_ALIGNMENT 4 #define GDMA_LL_AHB_RX_BURST_NEEDS_ALIGNMENT 1 diff --git a/components/hal/esp32c5/include/hal/ahb_dma_ll.h b/components/hal/esp32c5/include/hal/ahb_dma_ll.h index 787edf0ec5..4ea87aef8c 100644 --- a/components/hal/esp32c5/include/hal/ahb_dma_ll.h +++ b/components/hal/esp32c5/include/hal/ahb_dma_ll.h @@ -48,6 +48,8 @@ extern "C" { #define GDMA_LL_AHB_NUM_GROUPS 1 // Number of AHB GDMA groups #define GDMA_LL_AHB_PAIRS_PER_GROUP 3 // Number of GDMA pairs in each AHB group +#define GDMA_LL_AHB_M2M_CAPABLE_PAIR_MASK 0x07 // pair 0,1,2 are M2M capable + #define GDMA_LL_TX_ETM_EVENT_TABLE(group, chan, event) \ (uint32_t[1][3][GDMA_ETM_EVENT_MAX]){{{ \ [GDMA_ETM_EVENT_EOF] = GDMA_EVT_OUT_EOF_CH0, \ diff --git a/components/hal/esp32c6/include/hal/gdma_ll.h b/components/hal/esp32c6/include/hal/gdma_ll.h index 5a1d8d2417..62f4dea119 100644 --- a/components/hal/esp32c6/include/hal/gdma_ll.h +++ b/components/hal/esp32c6/include/hal/gdma_ll.h @@ -47,6 +47,8 @@ extern "C" { #define GDMA_LL_AHB_NUM_GROUPS 1 // Number of AHB GDMA groups #define GDMA_LL_AHB_PAIRS_PER_GROUP 3 // Number of GDMA pairs in each AHB group +#define GDMA_LL_AHB_M2M_CAPABLE_PAIR_MASK 0x07 // pair 0,1,2 are M2M capable + #define GDMA_LL_AHB_DESC_ALIGNMENT 4 #define GDMA_LL_AHB_RX_BURST_NEEDS_ALIGNMENT 1 diff --git a/components/hal/esp32c61/include/hal/ahb_dma_ll.h b/components/hal/esp32c61/include/hal/ahb_dma_ll.h index d2f5f95bfb..67a789970a 100644 --- a/components/hal/esp32c61/include/hal/ahb_dma_ll.h +++ b/components/hal/esp32c61/include/hal/ahb_dma_ll.h @@ -48,6 +48,8 @@ extern "C" { #define GDMA_LL_AHB_NUM_GROUPS 1 // Number of AHB GDMA groups #define GDMA_LL_AHB_PAIRS_PER_GROUP 2 // Number of GDMA pairs in each AHB group +#define GDMA_LL_AHB_M2M_CAPABLE_PAIR_MASK 0x03 // pair 0,1 are M2M capable + #define GDMA_LL_TX_ETM_EVENT_TABLE(group, chan, event) \ (uint32_t[1][2][GDMA_ETM_EVENT_MAX]){{{ \ [GDMA_ETM_EVENT_EOF] = GDMA_EVT_OUT_EOF_CH0, \ diff --git a/components/hal/esp32h2/include/hal/gdma_ll.h b/components/hal/esp32h2/include/hal/gdma_ll.h index 5a1d8d2417..62f4dea119 100644 --- a/components/hal/esp32h2/include/hal/gdma_ll.h +++ b/components/hal/esp32h2/include/hal/gdma_ll.h @@ -47,6 +47,8 @@ extern "C" { #define GDMA_LL_AHB_NUM_GROUPS 1 // Number of AHB GDMA groups #define GDMA_LL_AHB_PAIRS_PER_GROUP 3 // Number of GDMA pairs in each AHB group +#define GDMA_LL_AHB_M2M_CAPABLE_PAIR_MASK 0x07 // pair 0,1,2 are M2M capable + #define GDMA_LL_AHB_DESC_ALIGNMENT 4 #define GDMA_LL_AHB_RX_BURST_NEEDS_ALIGNMENT 1 diff --git a/components/hal/esp32h21/include/hal/gdma_ll.h b/components/hal/esp32h21/include/hal/gdma_ll.h index bf145e4778..4d0f42c613 100644 --- a/components/hal/esp32h21/include/hal/gdma_ll.h +++ b/components/hal/esp32h21/include/hal/gdma_ll.h @@ -50,6 +50,8 @@ extern "C" { #define GDMA_LL_AHB_DESC_ALIGNMENT 4 #define GDMA_LL_AHB_RX_BURST_NEEDS_ALIGNMENT 1 +#define GDMA_LL_AHB_M2M_CAPABLE_PAIR_MASK 0x07 // pair 0,1,2 are M2M capable + #define GDMA_LL_TX_ETM_EVENT_TABLE(group, chan, event) \ (uint32_t[1][3][GDMA_ETM_EVENT_MAX]){{{ \ [GDMA_ETM_EVENT_EOF] = GDMA_EVT_OUT_EOF_CH0, \ diff --git a/components/hal/esp32h4/include/hal/ahb_dma_ll.h b/components/hal/esp32h4/include/hal/ahb_dma_ll.h index facd2dab5a..addac62de0 100644 --- a/components/hal/esp32h4/include/hal/ahb_dma_ll.h +++ b/components/hal/esp32h4/include/hal/ahb_dma_ll.h @@ -48,6 +48,8 @@ extern "C" { #define GDMA_LL_AHB_NUM_GROUPS 1 // Number of AHB GDMA groups #define GDMA_LL_AHB_PAIRS_PER_GROUP 5 // Number of GDMA pairs in each AHB group +#define GDMA_LL_AHB_M2M_CAPABLE_PAIR_MASK 0x1F // pair 0,1,2,3,4 are M2M capable + #define GDMA_LL_TX_ETM_EVENT_TABLE(group, chan, event) \ (uint32_t[1][5][GDMA_ETM_EVENT_MAX]){{{ \ [GDMA_ETM_EVENT_EOF] = GDMA_EVT_OUT_EOF_CH0, \ diff --git a/components/hal/esp32p4/include/hal/gdma_ll.h b/components/hal/esp32p4/include/hal/gdma_ll.h index 3f1410a1a6..6316a33f94 100644 --- a/components/hal/esp32p4/include/hal/gdma_ll.h +++ b/components/hal/esp32p4/include/hal/gdma_ll.h @@ -54,6 +54,14 @@ #define GDMA_LL_AHB_BURST_SIZE_ADJUSTABLE 1 // AHB GDMA supports adjustable burst size #endif +#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300 +#define GDMA_LL_AHB_M2M_CAPABLE_PAIR_MASK 0x06 // only pair 1,2 are M2M capable +#else +#define GDMA_LL_AHB_M2M_CAPABLE_PAIR_MASK 0x07 // pair 0,1,2 are M2M capable +#endif + +#define GDMA_LL_AXI_M2M_CAPABLE_PAIR_MASK 0x07 // pair 0,1,2 are M2M capable + #define GDMA_LL_TX_ETM_EVENT_TABLE(group, chan, event) \ (uint32_t[2][GDMA_ETM_EVENT_MAX]){ \ { \ diff --git a/components/hal/esp32s3/include/hal/gdma_ll.h b/components/hal/esp32s3/include/hal/gdma_ll.h index d69c74fd1e..58cc22253c 100644 --- a/components/hal/esp32s3/include/hal/gdma_ll.h +++ b/components/hal/esp32s3/include/hal/gdma_ll.h @@ -66,6 +66,8 @@ extern "C" { #define GDMA_LL_AHB_RX_BURST_NEEDS_ALIGNMENT 1 #define GDMA_LL_MAX_BURST_SIZE_PSRAM 64 // PSRAM controller doesn't support burst access with size > 64 bytes +#define GDMA_LL_AHB_M2M_CAPABLE_PAIR_MASK 0x1F // pair 0,1,2,3,4 are M2M capable + ///////////////////////////////////// Common ///////////////////////////////////////// /**