From 1dfce4409a9d8dff6fe39e5b79e0a78a3cdce9d4 Mon Sep 17 00:00:00 2001 From: Chen Chen Date: Thu, 20 Aug 2026 15:51:10 +0800 Subject: [PATCH] feat(gdma): add burst size validation check during config Co-authored-by: Cursor --- .../esp_driver_dma/include/esp_private/gdma.h | 2 +- components/esp_driver_dma/src/gdma.c | 10 ++- .../test_apps/dma/main/test_gdma.c | 63 +++++++++++++++++++ .../esp_driver_spi/src/gpspi/spi_common.c | 8 +-- .../esp32c5/include/hal/ahb_dma_ll.h | 7 ++- .../esp32c61/include/hal/ahb_dma_ll.h | 4 ++ .../esp32h4/include/hal/ahb_dma_ll.h | 7 ++- .../esp32p4/include/hal/ahb_dma_ll.h | 7 ++- .../esp32p4/include/hal/axi_dma_ll.h | 6 ++ .../esp_hal_dma/esp32s3/include/hal/gdma_ll.h | 4 ++ .../esp32s31/include/hal/ahb_dma_ll.h | 5 ++ .../esp32s31/include/hal/axi_dma_ll.h | 6 ++ components/esp_hal_dma/gdma_hal_ahb_v1.c | 3 + components/esp_hal_dma/gdma_hal_ahb_v2.c | 6 ++ components/esp_hal_dma/gdma_hal_axi.c | 1 + components/esp_hal_dma/gdma_hal_top.c | 13 ++++ components/esp_hal_dma/include/hal/gdma_hal.h | 4 ++ .../esp_hal_dma/include/hal/gdma_types.h | 14 ++++- 18 files changed, 154 insertions(+), 16 deletions(-) diff --git a/components/esp_driver_dma/include/esp_private/gdma.h b/components/esp_driver_dma/include/esp_private/gdma.h index 2943914ecf2..219004c083c 100644 --- a/components/esp_driver_dma/include/esp_private/gdma.h +++ b/components/esp_driver_dma/include/esp_private/gdma.h @@ -202,7 +202,7 @@ esp_err_t gdma_disconnect(gdma_channel_handle_t dma_chan); typedef struct { uint32_t max_data_burst_size; /*!< Set the max burst size when DMA read/write the data buffer. Set to 0 means to disable the data burst. - Other value must be power of 2, e.g., 4/8/16/32/64 */ + Other values must be powers of 2 or supported by the selected GDMA bus. */ bool access_ext_mem; /*!< Set this if the DMA transfer will access external memory */ } gdma_transfer_config_t; diff --git a/components/esp_driver_dma/src/gdma.c b/components/esp_driver_dma/src/gdma.c index fcd4be042c0..d555bfa632b 100644 --- a/components/esp_driver_dma/src/gdma.c +++ b/components/esp_driver_dma/src/gdma.c @@ -421,6 +421,9 @@ esp_err_t gdma_config_transfer(gdma_channel_handle_t dma_chan, const gdma_transf return ESP_ERR_INVALID_ARG; } + gdma_pair_t *pair = dma_chan->pair; + gdma_group_t *group = pair->group; + gdma_hal_context_t *hal = &group->hal; uint32_t max_data_burst_size = config->max_data_burst_size; size_t int_mem_alignment = 1; size_t ext_enc_mem_alignment = 1; @@ -443,8 +446,7 @@ esp_err_t gdma_config_transfer(gdma_channel_handle_t dma_chan, const gdma_transf #endif } if (max_data_burst_size) { - // burst size must be power of 2 - ESP_RETURN_ON_FALSE((max_data_burst_size & (max_data_burst_size - 1)) == 0, ESP_ERR_INVALID_ARG, + ESP_RETURN_ON_FALSE(gdma_hal_check_burst_size(hal, max_data_burst_size), ESP_ERR_INVALID_ARG, TAG, "invalid max_data_burst_size: %"PRIu32, max_data_burst_size); } @@ -477,10 +479,6 @@ esp_err_t gdma_config_transfer(gdma_channel_handle_t dma_chan, const gdma_transf ext_no_enc_mem_alignment = BIT(31); } - gdma_pair_t *pair = dma_chan->pair; - gdma_group_t *group = pair->group; - gdma_hal_context_t *hal = &group->hal; - // always enable descriptor burst as the descriptor is always word aligned and is in the internal SRAM bool en_desc_burst = true; gdma_hal_enable_burst(hal, pair->pair_id, dma_chan->direction, en_data_burst, en_desc_burst); diff --git a/components/esp_driver_dma/test_apps/dma/main/test_gdma.c b/components/esp_driver_dma/test_apps/dma/main/test_gdma.c index dcb16822b1b..8f39f97e865 100644 --- a/components/esp_driver_dma/test_apps/dma/main/test_gdma.c +++ b/components/esp_driver_dma/test_apps/dma/main/test_gdma.c @@ -921,3 +921,66 @@ TEST_CASE("GDMA interrupt priority configuration", "[GDMA]") TEST_ESP_OK(gdma_del_channel(tx_chan)); TEST_ESP_OK(gdma_del_channel(rx_chan)); } + +#if SOC_HAS(AHB_GDMA) +TEST_CASE("GDMA rejects invalid AHB burst sizes", "[GDMA]") +{ + gdma_channel_handle_t tx_chan = NULL; + gdma_channel_alloc_config_t channel_config = {}; + TEST_ESP_OK(gdma_new_ahb_channel(&channel_config, &tx_chan, NULL)); + + gdma_transfer_config_t transfer_config = { + .max_data_burst_size = 16, + .access_ext_mem = false, + }; + TEST_ESP_OK(gdma_config_transfer(tx_chan, &transfer_config)); + +#if GDMA_LL_GET(AHB_BURST_SIZE_ADJUSTABLE) + // Non power-of-two must be rejected when the burst size is programmable. + transfer_config.max_data_burst_size = 3; + TEST_ESP_ERR(ESP_ERR_INVALID_ARG, gdma_config_transfer(tx_chan, &transfer_config)); + + // 8 is a power of two but is outside every current AHB supported-burst mask. + transfer_config.max_data_burst_size = 8; + TEST_ESP_ERR(ESP_ERR_INVALID_ARG, gdma_config_transfer(tx_chan, &transfer_config)); + +#if GDMA_LL_GET(AHB_PSRAM_CAPABLE) + transfer_config.access_ext_mem = true; + transfer_config.max_data_burst_size = GDMA_LL_MAX_BURST_SIZE_PSRAM * 2; + TEST_ESP_ERR(ESP_ERR_INVALID_ARG, gdma_config_transfer(tx_chan, &transfer_config)); +#endif // GDMA_LL_GET(AHB_PSRAM_CAPABLE) +#endif // GDMA_LL_GET(AHB_BURST_SIZE_ADJUSTABLE) + + TEST_ESP_OK(gdma_del_channel(tx_chan)); +} +#endif // SOC_HAS(AHB_GDMA) + +#if SOC_HAS(AXI_GDMA) +TEST_CASE("GDMA rejects invalid AXI burst sizes", "[GDMA]") +{ + gdma_channel_handle_t tx_chan = NULL; + gdma_channel_alloc_config_t channel_config = {}; + TEST_ESP_OK(gdma_new_axi_channel(&channel_config, &tx_chan, NULL)); + + gdma_transfer_config_t transfer_config = { + .max_data_burst_size = 16, + .access_ext_mem = false, + }; + TEST_ESP_OK(gdma_config_transfer(tx_chan, &transfer_config)); + + transfer_config.max_data_burst_size = 3; + TEST_ESP_ERR(ESP_ERR_INVALID_ARG, gdma_config_transfer(tx_chan, &transfer_config)); + + // 4 is a power of two but is outside the AXI supported-burst mask. + transfer_config.max_data_burst_size = 4; + TEST_ESP_ERR(ESP_ERR_INVALID_ARG, gdma_config_transfer(tx_chan, &transfer_config)); + +#if GDMA_LL_GET(AXI_PSRAM_CAPABLE) + transfer_config.access_ext_mem = true; + transfer_config.max_data_burst_size = GDMA_LL_MAX_BURST_SIZE_PSRAM * 2; + TEST_ESP_ERR(ESP_ERR_INVALID_ARG, gdma_config_transfer(tx_chan, &transfer_config)); +#endif // GDMA_LL_GET(AXI_PSRAM_CAPABLE) + + TEST_ESP_OK(gdma_del_channel(tx_chan)); +} +#endif // SOC_HAS(AXI_GDMA) diff --git a/components/esp_driver_spi/src/gpspi/spi_common.c b/components/esp_driver_spi/src/gpspi/spi_common.c index f4b7ea637c5..51b8fe91e8e 100644 --- a/components/esp_driver_spi/src/gpspi/spi_common.c +++ b/components/esp_driver_spi/src/gpspi/spi_common.c @@ -267,7 +267,7 @@ static esp_err_t alloc_dma_chan(spi_host_device_t host_id, spi_dma_chan_t dma_ch #define SPI_GDMA_NEW_CHANNEL gdma_new_ahb_channel #endif -static esp_err_t resolve_dma_burst_size(uint32_t requested, uint32_t *out_burst_size) +static uint32_t resolve_dma_burst_size(uint32_t requested) { uint32_t burst_size = requested; if (burst_size == 0) { @@ -280,8 +280,7 @@ static esp_err_t resolve_dma_burst_size(uint32_t requested, uint32_t *out_burst_ } burst_size = SPI_DMA_DEFAULT_BURST_SIZE; #endif - *out_burst_size = burst_size; - return ESP_OK; + return burst_size; } static esp_err_t alloc_dma_chan(spi_host_device_t host_id, spi_dma_chan_t dma_chan, uint32_t dma_burst_size, spi_dma_ctx_t *dma_ctx) @@ -291,8 +290,7 @@ static esp_err_t alloc_dma_chan(spi_host_device_t host_id, spi_dma_chan_t dma_ch esp_err_t ret = ESP_OK; if (dma_chan == SPI_DMA_CH_AUTO) { - uint32_t burst_size = SPI_DMA_DEFAULT_BURST_SIZE; - ESP_RETURN_ON_ERROR(resolve_dma_burst_size(dma_burst_size, &burst_size), SPI_TAG, "invalid dma_burst_size"); + uint32_t burst_size = resolve_dma_burst_size(dma_burst_size); gdma_channel_alloc_config_t alloc_config = { #if CONFIG_SPI_MASTER_ISR_IN_IRAM diff --git a/components/esp_hal_dma/esp32c5/include/hal/ahb_dma_ll.h b/components/esp_hal_dma/esp32c5/include/hal/ahb_dma_ll.h index f757652c380..1ea640793b2 100644 --- a/components/esp_hal_dma/esp32c5/include/hal/ahb_dma_ll.h +++ b/components/esp_hal_dma/esp32c5/include/hal/ahb_dma_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -21,6 +21,11 @@ extern "C" { #define AHB_DMA_LL_GET_HW(id) (((id) == 0) ? (&AHB_DMA) : NULL) +#define AHB_DMA_LL_SUPPORTED_BURST_SIZE_MASK (GDMA_BURST_SIZE_SUPPORT_4 | \ + GDMA_BURST_SIZE_SUPPORT_16 | \ + GDMA_BURST_SIZE_SUPPORT_32 | \ + GDMA_BURST_SIZE_SUPPORT_64) + #define GDMA_LL_CHANNEL_MAX_PRIORITY 5 // supported priority levels: [0,5] #define GDMA_LL_CHANNEL_MAX_WEIGHT 15 // supported weight levels: [0,15] diff --git a/components/esp_hal_dma/esp32c61/include/hal/ahb_dma_ll.h b/components/esp_hal_dma/esp32c61/include/hal/ahb_dma_ll.h index b5ae691b50e..3e936b5f385 100644 --- a/components/esp_hal_dma/esp32c61/include/hal/ahb_dma_ll.h +++ b/components/esp_hal_dma/esp32c61/include/hal/ahb_dma_ll.h @@ -21,6 +21,10 @@ extern "C" { #define AHB_DMA_LL_GET_HW(id) (((id) == 0) ? (&AHB_DMA) : NULL) +#define AHB_DMA_LL_SUPPORTED_BURST_SIZE_MASK (GDMA_BURST_SIZE_SUPPORT_4 | \ + GDMA_BURST_SIZE_SUPPORT_16 | \ + GDMA_BURST_SIZE_SUPPORT_32) + #define GDMA_LL_CHANNEL_MAX_PRIORITY 5 // supported priority levels: [0,5] #define GDMA_LL_CHANNEL_MAX_WEIGHT 15 // supported weight levels: [0,15] diff --git a/components/esp_hal_dma/esp32h4/include/hal/ahb_dma_ll.h b/components/esp_hal_dma/esp32h4/include/hal/ahb_dma_ll.h index 30a97a2fc10..b5becda79b7 100644 --- a/components/esp_hal_dma/esp32h4/include/hal/ahb_dma_ll.h +++ b/components/esp_hal_dma/esp32h4/include/hal/ahb_dma_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -21,6 +21,11 @@ extern "C" { #define AHB_DMA_LL_GET_HW(id) (((id) == 0) ? (&AHB_DMA) : NULL) +#define AHB_DMA_LL_SUPPORTED_BURST_SIZE_MASK (GDMA_BURST_SIZE_SUPPORT_4 | \ + GDMA_BURST_SIZE_SUPPORT_16 | \ + GDMA_BURST_SIZE_SUPPORT_32 | \ + GDMA_BURST_SIZE_SUPPORT_64) + #define GDMA_LL_CHANNEL_MAX_PRIORITY 5 // supported priority levels: [0,5] #define AHB_DMA_LL_RX_EVENT_MASK (0x7F) diff --git a/components/esp_hal_dma/esp32p4/include/hal/ahb_dma_ll.h b/components/esp_hal_dma/esp32p4/include/hal/ahb_dma_ll.h index b96f2267e9e..49eac86ef6a 100644 --- a/components/esp_hal_dma/esp32p4/include/hal/ahb_dma_ll.h +++ b/components/esp_hal_dma/esp32p4/include/hal/ahb_dma_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -22,6 +22,11 @@ extern "C" { #define AHB_DMA_LL_GET_HW(id) (((id) == 0) ? (&AHB_DMA) : NULL) +#define AHB_DMA_LL_SUPPORTED_BURST_SIZE_MASK (GDMA_BURST_SIZE_SUPPORT_4 | \ + GDMA_BURST_SIZE_SUPPORT_16 | \ + GDMA_BURST_SIZE_SUPPORT_32 | \ + GDMA_BURST_SIZE_SUPPORT_64) + // any "dummy" peripheral ID can be used for M2M mode #define AHB_DMA_LL_M2M_FREE_PERIPH_ID_MASK (0xFAC2) #define AHB_DMA_LL_RX_EVENT_MASK (0x1F) diff --git a/components/esp_hal_dma/esp32p4/include/hal/axi_dma_ll.h b/components/esp_hal_dma/esp32p4/include/hal/axi_dma_ll.h index 7717aad3371..2782c27d9fd 100644 --- a/components/esp_hal_dma/esp32p4/include/hal/axi_dma_ll.h +++ b/components/esp_hal_dma/esp32p4/include/hal/axi_dma_ll.h @@ -24,6 +24,12 @@ extern "C" { #define AXI_DMA_LL_GET_HW(id) (((id) == 0) ? (&AXI_DMA) : NULL) #define AXI_DMA_LL_SUPPORT(_feat) AXI_DMA_LL_SUPPORT_ ## _feat +#define AXI_DMA_LL_SUPPORTED_BURST_SIZE_MASK (GDMA_BURST_SIZE_SUPPORT_8 | \ + GDMA_BURST_SIZE_SUPPORT_16 | \ + GDMA_BURST_SIZE_SUPPORT_32 | \ + GDMA_BURST_SIZE_SUPPORT_64 | \ + GDMA_BURST_SIZE_SUPPORT_128) + // any "dummy" peripheral ID can be used for M2M mode #define AXI_DMA_LL_M2M_FREE_PERIPH_ID_MASK (0xFFC0) #define AXI_DMA_LL_RX_EVENT_MASK (0x1F) diff --git a/components/esp_hal_dma/esp32s3/include/hal/gdma_ll.h b/components/esp_hal_dma/esp32s3/include/hal/gdma_ll.h index 43af26638ee..a7f07bdf3da 100644 --- a/components/esp_hal_dma/esp32s3/include/hal/gdma_ll.h +++ b/components/esp_hal_dma/esp32s3/include/hal/gdma_ll.h @@ -19,6 +19,10 @@ #define GDMA_LL_INST_NUM 1 #define GDMA_LL_PAIRS_PER_INST GDMA_LL_AHB_PAIRS_PER_GROUP +#define GDMA_LL_AHB_SUPPORTED_BURST_SIZE_MASK (GDMA_BURST_SIZE_SUPPORT_16 | \ + GDMA_BURST_SIZE_SUPPORT_32 | \ + GDMA_BURST_SIZE_SUPPORT_64) + #ifdef __cplusplus extern "C" { #endif diff --git a/components/esp_hal_dma/esp32s31/include/hal/ahb_dma_ll.h b/components/esp_hal_dma/esp32s31/include/hal/ahb_dma_ll.h index 4528aaa3640..080d5d81a12 100644 --- a/components/esp_hal_dma/esp32s31/include/hal/ahb_dma_ll.h +++ b/components/esp_hal_dma/esp32s31/include/hal/ahb_dma_ll.h @@ -20,6 +20,11 @@ extern "C" { #define AHB_DMA_LL_GET_HW(id) (((id) == 0) ? (&AHB_DMA) : (((id) == 2) ? ((ahb_dma_dev_t *)&LP_AHB_DMA) : NULL)) +#define AHB_DMA_LL_SUPPORTED_BURST_SIZE_MASK (GDMA_BURST_SIZE_SUPPORT_4 | \ + GDMA_BURST_SIZE_SUPPORT_16 | \ + GDMA_BURST_SIZE_SUPPORT_32 | \ + GDMA_BURST_SIZE_SUPPORT_64) + // any "dummy" peripheral ID can be used for M2M mode #define AHB_DMA_LL_M2M_FREE_PERIPH_ID_MASK (0x8200) #define AHB_DMA_LL_RX_EVENT_MASK (0x7F) diff --git a/components/esp_hal_dma/esp32s31/include/hal/axi_dma_ll.h b/components/esp_hal_dma/esp32s31/include/hal/axi_dma_ll.h index a5f8083d09a..8cb5fd3dda0 100644 --- a/components/esp_hal_dma/esp32s31/include/hal/axi_dma_ll.h +++ b/components/esp_hal_dma/esp32s31/include/hal/axi_dma_ll.h @@ -23,6 +23,12 @@ extern "C" { #define AXI_DMA_LL_GET_HW(id) (((id) == 0) ? (&AXI_DMA) : NULL) #define AXI_DMA_LL_SUPPORT(_feat) AXI_DMA_LL_SUPPORT_ ## _feat +#define AXI_DMA_LL_SUPPORTED_BURST_SIZE_MASK (GDMA_BURST_SIZE_SUPPORT_8 | \ + GDMA_BURST_SIZE_SUPPORT_16 | \ + GDMA_BURST_SIZE_SUPPORT_32 | \ + GDMA_BURST_SIZE_SUPPORT_64 | \ + GDMA_BURST_SIZE_SUPPORT_128) + // any "dummy" peripheral ID can be used for M2M mode #define AXI_DMA_LL_M2M_FREE_PERIPH_ID_MASK (0xFFC0) #define AXI_DMA_LL_RX_EVENT_MASK (0x7F) diff --git a/components/esp_hal_dma/gdma_hal_ahb_v1.c b/components/esp_hal_dma/gdma_hal_ahb_v1.c index 10b7c1a668e..650c23604e6 100644 --- a/components/esp_hal_dma/gdma_hal_ahb_v1.c +++ b/components/esp_hal_dma/gdma_hal_ahb_v1.c @@ -13,6 +13,9 @@ static gdma_hal_priv_data_t gdma_ahb_hal_priv_data = { .m2m_free_periph_mask = GDMA_LL_M2M_FREE_PERIPH_ID_MASK, .tx_event_mask = GDMA_LL_TX_EVENT_MASK, .rx_event_mask = GDMA_LL_RX_EVENT_MASK, +#if GDMA_LL_GET(AHB_BURST_SIZE_ADJUSTABLE) + .supported_burst_size_mask = GDMA_LL_AHB_SUPPORTED_BURST_SIZE_MASK, +#endif }; void gdma_ahb_hal_start_with_desc(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, intptr_t desc_base_addr) diff --git a/components/esp_hal_dma/gdma_hal_ahb_v2.c b/components/esp_hal_dma/gdma_hal_ahb_v2.c index 69e1a48323e..4527b6b72b9 100644 --- a/components/esp_hal_dma/gdma_hal_ahb_v2.c +++ b/components/esp_hal_dma/gdma_hal_ahb_v2.c @@ -14,6 +14,9 @@ static gdma_hal_priv_data_t gdma_ahb_hal_priv_data = { .m2m_free_periph_mask = AHB_DMA_LL_M2M_FREE_PERIPH_ID_MASK, .tx_event_mask = AHB_DMA_LL_TX_EVENT_MASK, .rx_event_mask = AHB_DMA_LL_RX_EVENT_MASK, +#if GDMA_LL_GET(AHB_BURST_SIZE_ADJUSTABLE) + .supported_burst_size_mask = AHB_DMA_LL_SUPPORTED_BURST_SIZE_MASK, +#endif }; void gdma_ahb_hal_start_with_desc(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, intptr_t desc_base_addr) @@ -315,6 +318,9 @@ static gdma_hal_priv_data_t gdma_lp_ahb_hal_priv_data = { .m2m_free_periph_mask = LP_AHB_DMA_LL_M2M_FREE_PERIPH_ID_MASK, .tx_event_mask = AHB_DMA_LL_TX_EVENT_MASK, .rx_event_mask = AHB_DMA_LL_RX_EVENT_MASK, +#if GDMA_LL_GET(AHB_BURST_SIZE_ADJUSTABLE) + .supported_burst_size_mask = AHB_DMA_LL_SUPPORTED_BURST_SIZE_MASK, +#endif }; void gdma_lp_ahb_hal_init(gdma_hal_context_t *hal, const gdma_hal_config_t *config) diff --git a/components/esp_hal_dma/gdma_hal_axi.c b/components/esp_hal_dma/gdma_hal_axi.c index d235964be3a..fe76bf33aec 100644 --- a/components/esp_hal_dma/gdma_hal_axi.c +++ b/components/esp_hal_dma/gdma_hal_axi.c @@ -14,6 +14,7 @@ static gdma_hal_priv_data_t gdma_axi_hal_priv_data = { .m2m_free_periph_mask = AXI_DMA_LL_M2M_FREE_PERIPH_ID_MASK, .tx_event_mask = AXI_DMA_LL_TX_EVENT_MASK, .rx_event_mask = AXI_DMA_LL_RX_EVENT_MASK, + .supported_burst_size_mask = AXI_DMA_LL_SUPPORTED_BURST_SIZE_MASK, }; void gdma_axi_hal_start_with_desc(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, intptr_t desc_base_addr) diff --git a/components/esp_hal_dma/gdma_hal_top.c b/components/esp_hal_dma/gdma_hal_top.c index 71bc6ef6de6..9d8d08c7ea1 100644 --- a/components/esp_hal_dma/gdma_hal_top.c +++ b/components/esp_hal_dma/gdma_hal_top.c @@ -65,6 +65,19 @@ void gdma_hal_set_burst_size(gdma_hal_context_t *hal, int chan_id, gdma_channel_ } } +bool gdma_hal_check_burst_size(gdma_hal_context_t *hal, uint32_t burst_sz) +{ + if (burst_sz & (burst_sz - 1)) { + // Not a power of 2 + return false; + } + if (!hal->set_burst_size) { + // When a specific burst size cannot be set (using fixed burst size) + return true; + } + return (hal->priv_data->supported_burst_size_mask & burst_sz) != 0; +} + void gdma_hal_set_strategy(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, bool en_owner_check, bool en_desc_write_back, bool eof_till_popped) { hal->set_strategy(hal, chan_id, dir, en_owner_check, en_desc_write_back, eof_till_popped); diff --git a/components/esp_hal_dma/include/hal/gdma_hal.h b/components/esp_hal_dma/include/hal/gdma_hal.h index 60fe7b970ed..8432b5eaf8b 100644 --- a/components/esp_hal_dma/include/hal/gdma_hal.h +++ b/components/esp_hal_dma/include/hal/gdma_hal.h @@ -55,6 +55,8 @@ typedef struct { // Supported interrupt events can vary across DMA instances (e.g. AHB vs AXI) uint32_t tx_event_mask; uint32_t rx_event_mask; + // Bitmap of supported configurable data burst sizes, using gdma_burst_size_support_t + uint32_t supported_burst_size_mask; } gdma_hal_priv_data_t; /** @@ -128,6 +130,8 @@ void gdma_hal_enable_burst(gdma_hal_context_t *hal, int chan_id, gdma_channel_di void gdma_hal_set_burst_size(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, uint32_t burst_sz); +bool gdma_hal_check_burst_size(gdma_hal_context_t *hal, uint32_t burst_sz); + void gdma_hal_set_strategy(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, bool en_owner_check, bool en_desc_write_back, bool eof_till_popped); void gdma_hal_enable_intr(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, uint32_t intr_event_mask, bool en_or_dis); diff --git a/components/esp_hal_dma/include/hal/gdma_types.h b/components/esp_hal_dma/include/hal/gdma_types.h index d2b47cc2986..1ce3bf94c80 100644 --- a/components/esp_hal_dma/include/hal/gdma_types.h +++ b/components/esp_hal_dma/include/hal/gdma_types.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -22,6 +22,18 @@ typedef enum { GDMA_CHANNEL_DIRECTION_RX, /*!< GDMA channel direction: RX */ } gdma_channel_direction_t; +/** + * @brief Bit definitions used by the LL layer to describe supported data burst sizes + */ +typedef enum { + GDMA_BURST_SIZE_SUPPORT_4 = 1U << 2, + GDMA_BURST_SIZE_SUPPORT_8 = 1U << 3, + GDMA_BURST_SIZE_SUPPORT_16 = 1U << 4, + GDMA_BURST_SIZE_SUPPORT_32 = 1U << 5, + GDMA_BURST_SIZE_SUPPORT_64 = 1U << 6, + GDMA_BURST_SIZE_SUPPORT_128 = 1U << 7, +} gdma_burst_size_support_t; + /** * @brief GDMA channel events that supported by the ETM module */