diff --git a/components/esp_adc/esp32s2/adc_dma.c b/components/esp_adc/esp32s2/adc_dma.c index e1fe2153fd..4060b82a3f 100644 --- a/components/esp_adc/esp32s2/adc_dma.c +++ b/components/esp_adc/esp32s2/adc_dma.c @@ -58,7 +58,7 @@ esp_err_t adc_dma_init(adc_dma_t *adc_dma) if (spi_success != true) { return ESP_FAIL; } - ret = spicommon_dma_chan_alloc(ADC_DMA_SPI_HOST, SPI_DMA_CH_AUTO); + ret = spicommon_dma_chan_alloc(ADC_DMA_SPI_HOST, SPI_DMA_CH_AUTO, 0); if (ret != ESP_OK) { return ret; } diff --git a/components/esp_driver_dac/esp32s2/dac_dma.c b/components/esp_driver_dac/esp32s2/dac_dma.c index fa6c98a20b..ad10e62f84 100644 --- a/components/esp_driver_dac/esp32s2/dac_dma.c +++ b/components/esp_driver_dac/esp32s2/dac_dma.c @@ -144,7 +144,7 @@ esp_err_t dac_dma_periph_init(uint32_t freq_hz, bool is_alternate, bool is_apll) /* When transmit alternately, twice frequency is needed to guarantee the convert frequency in one channel */ uint32_t trans_freq_hz = freq_hz * (is_alternate ? 2 : 1); ESP_GOTO_ON_ERROR(s_dac_dma_periph_set_clock(trans_freq_hz, is_apll), err, TAG, "Failed to set clock of DMA peripheral"); - ESP_GOTO_ON_ERROR(spicommon_dma_chan_alloc(DAC_DMA_PERIPH_SPI_HOST, SPI_DMA_CH_AUTO), + ESP_GOTO_ON_ERROR(spicommon_dma_chan_alloc(DAC_DMA_PERIPH_SPI_HOST, SPI_DMA_CH_AUTO, 0), err, TAG, "Failed to allocate dma peripheral channel"); s_ddp->dma_chan = spi_bus_get_dma_ctx(DAC_DMA_PERIPH_SPI_HOST)->rx_dma_chan.chan_id; spi_ll_enable_intr(s_ddp->periph_dev, SPI_LL_INTR_OUT_EOF | SPI_LL_INTR_OUT_TOTAL_EOF); diff --git a/components/esp_driver_dma/src/gdma.c b/components/esp_driver_dma/src/gdma.c index 4c54195d89..60dbfd50ad 100644 --- a/components/esp_driver_dma/src/gdma.c +++ b/components/esp_driver_dma/src/gdma.c @@ -412,9 +412,22 @@ esp_err_t gdma_config_transfer(gdma_channel_handle_t dma_chan, const gdma_transf } uint32_t max_data_burst_size = config->max_data_burst_size; if (max_data_burst_size) { +#if defined(GDMA_LL_SUPPORTED_BURST_SIZES_ARRAY) + uint32_t supported_burst_sizes[] = GDMA_LL_SUPPORTED_BURST_SIZES_ARRAY; + bool valid = false; + for (size_t i = 0; i < sizeof(supported_burst_sizes) / sizeof(supported_burst_sizes[0]); i++) { + if (supported_burst_sizes[i] == max_data_burst_size) { + valid = true; + break; + } + } + ESP_RETURN_ON_FALSE(valid, ESP_ERR_INVALID_ARG, TAG, + "invalid max_data_burst_size (%" PRIu32 "), supported: %s", max_data_burst_size, GDMA_LL_SUPPORTED_BURST_SIZES_STR); +#else // 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, - TAG, "invalid max_data_burst_size: %"PRIu32, max_data_burst_size); + TAG, "invalid max_data_burst_size: %" PRIu32, max_data_burst_size); +#endif #if GDMA_LL_GET(AHB_PSRAM_CAPABLE) || GDMA_LL_GET(AXI_PSRAM_CAPABLE) || GDMA_LL_GET(LP_AHB_PSRAM_CAPABLE) if (config->access_ext_mem) { ESP_RETURN_ON_FALSE(max_data_burst_size <= GDMA_LL_MAX_BURST_SIZE_PSRAM, ESP_ERR_INVALID_ARG, diff --git a/components/esp_driver_spi/include/driver/spi_common.h b/components/esp_driver_spi/include/driver/spi_common.h index 859740127e..424b9b79f2 100644 --- a/components/esp_driver_spi/include/driver/spi_common.h +++ b/components/esp_driver_spi/include/driver/spi_common.h @@ -124,6 +124,7 @@ typedef struct { }; bool data_io_default_level; ///< Output data IO default level when no transaction. int max_transfer_sz; ///< Maximum transfer size, in bytes. Defaults to 4092 if 0 when DMA enabled, or to `SOC_SPI_MAXIMUM_BUFFER_SIZE` if DMA is disabled. + uint32_t dma_burst_size; ///< DMA data burst size in bytes. Only used when DMA is enabled. Set to 0 to use driver default. When non-zero, must be one of the chip-supported values (see GDMA driver or chip TRM). Ignored on chips that do not support configurable burst size. uint32_t flags; ///< Abilities of bus to be checked by the driver. Or-ed value of ``SPICOMMON_BUSFLAG_*`` flags. esp_intr_cpu_affinity_t isr_cpu_id; ///< Select cpu core to register SPI ISR. int intr_flags; /**< Interrupt flag for the bus to set the priority, and IRAM attribute, see diff --git a/components/esp_driver_spi/include/esp_private/spi_common_internal.h b/components/esp_driver_spi/include/esp_private/spi_common_internal.h index 99e80800ed..1b983c6e50 100644 --- a/components/esp_driver_spi/include/esp_private/spi_common_internal.h +++ b/components/esp_driver_spi/include/esp_private/spi_common_internal.h @@ -104,13 +104,15 @@ esp_err_t spicommon_bus_free(spi_host_device_t host_id); * * @param host_id SPI host ID * @param dma_chan DMA channel to be used + * @param dma_burst_size DMA data burst size in bytes. Set to 0 to use driver default (32). Only applied when chip supports configurable burst size. * * @return * - ESP_OK: On success + * - ESP_ERR_INVALID_ARG: Invalid dma_burst_size (not in chip-supported list) * - ESP_ERR_NO_MEM: No enough memory * - ESP_ERR_NOT_FOUND: There is no available DMA channel */ -esp_err_t spicommon_dma_chan_alloc(spi_host_device_t host_id, spi_dma_chan_t dma_chan); +esp_err_t spicommon_dma_chan_alloc(spi_host_device_t host_id, spi_dma_chan_t dma_chan, uint32_t dma_burst_size); /** * @brief Alloc DMA descriptors for SPI diff --git a/components/esp_driver_spi/src/gpspi/spi_common.c b/components/esp_driver_spi/src/gpspi/spi_common.c index d1e744f2ba..8c0a894741 100644 --- a/components/esp_driver_spi/src/gpspi/spi_common.c +++ b/components/esp_driver_spi/src/gpspi/spi_common.c @@ -25,6 +25,9 @@ #include "esp_private/sleep_retention.h" #include "esp_dma_utils.h" #include "hal/spi_hal.h" +#if SOC_GDMA_SUPPORTED +#include "hal/gdma_ll.h" +#endif #include "freertos/FreeRTOS.h" #if CONFIG_IDF_TARGET_ESP32 #include "soc/dport_reg.h" @@ -60,6 +63,8 @@ static const char *SPI_TAG = "spi_common"; }, \ } +#define SPI_DMA_DEFAULT_BURST_SIZE 32 + typedef struct { int host_id; _lock_t mutex; // mutex for controller @@ -199,7 +204,7 @@ static void connect_spi_and_dma(spi_host_device_t host, int dma_chan) #endif } -static esp_err_t alloc_dma_chan(spi_host_device_t host_id, spi_dma_chan_t dma_chan, spi_dma_ctx_t *dma_ctx) +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) { assert(is_valid_host(host_id)); #if CONFIG_IDF_TARGET_ESP32 @@ -207,6 +212,7 @@ static esp_err_t alloc_dma_chan(spi_host_device_t host_id, spi_dma_chan_t dma_ch #elif CONFIG_IDF_TARGET_ESP32S2 assert(dma_chan == (int)host_id || dma_chan == SPI_DMA_CH_AUTO); #endif + (void)dma_burst_size; // not used on chips without GDMA burst size config esp_err_t ret = ESP_OK; bool success = false; @@ -258,13 +264,33 @@ 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 alloc_dma_chan(spi_host_device_t host_id, spi_dma_chan_t dma_chan, spi_dma_ctx_t *dma_ctx) +static esp_err_t resolve_dma_burst_size(uint32_t requested, uint32_t *out_burst_size) +{ + uint32_t burst_size = requested; + if (burst_size == 0) { + burst_size = SPI_DMA_DEFAULT_BURST_SIZE; + ESP_LOGD(SPI_TAG, "dma_burst_size is 0, using default %d", SPI_DMA_DEFAULT_BURST_SIZE); + } +#if !SOC_AXI_GDMA_SUPPORTED && !GDMA_LL_AHB_BURST_SIZE_ADJUSTABLE + if (requested != 0) { + ESP_LOGD(SPI_TAG, "Chip does not support configurable DMA burst size, using default %d", SPI_DMA_DEFAULT_BURST_SIZE); + } + burst_size = SPI_DMA_DEFAULT_BURST_SIZE; +#endif + *out_burst_size = burst_size; + return ESP_OK; +} + +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) { assert(is_valid_host(host_id)); assert(dma_chan == SPI_DMA_CH_AUTO); 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"); + gdma_channel_alloc_config_t alloc_config = { #if CONFIG_SPI_MASTER_ISR_IN_IRAM .flags.isr_cache_safe = true, @@ -285,8 +311,10 @@ static esp_err_t alloc_dma_chan(spi_host_device_t host_id, spi_dma_chan_t dma_ch } #endif gdma_transfer_config_t trans_cfg = { - .max_data_burst_size = 32, + .max_data_burst_size = burst_size, +#if CONFIG_SPIRAM && SOC_PSRAM_DMA_CAPABLE .access_ext_mem = true, // allow to transfer data from/to external memory directly by DMA +#endif }; ESP_RETURN_ON_ERROR(gdma_config_transfer(dma_ctx->tx_dma_chan, &trans_cfg), SPI_TAG, "config gdma tx transfer failed"); ESP_RETURN_ON_ERROR(gdma_config_transfer(dma_ctx->rx_dma_chan, &trans_cfg), SPI_TAG, "config gdma rx transfer failed"); @@ -299,7 +327,7 @@ static esp_err_t alloc_dma_chan(spi_host_device_t host_id, spi_dma_chan_t dma_ch } #endif //#if !SOC_GDMA_SUPPORTED -esp_err_t spicommon_dma_chan_alloc(spi_host_device_t host_id, spi_dma_chan_t dma_chan) +esp_err_t spicommon_dma_chan_alloc(spi_host_device_t host_id, spi_dma_chan_t dma_chan, uint32_t dma_burst_size) { assert(is_valid_host(host_id)); #if CONFIG_IDF_TARGET_ESP32 @@ -315,7 +343,7 @@ esp_err_t spicommon_dma_chan_alloc(spi_host_device_t host_id, spi_dma_chan_t dma goto cleanup; } - ret = alloc_dma_chan(host_id, dma_chan, dma_ctx); + ret = alloc_dma_chan(host_id, dma_chan, dma_burst_size, dma_ctx); if (ret != ESP_OK) { goto cleanup; } @@ -907,7 +935,7 @@ esp_err_t spi_bus_initialize(spi_host_device_t host_id, const spi_bus_config_t * bus_attr->dma_enabled = (dma_chan != SPI_DMA_DISABLED); bus_attr->max_transfer_sz = SOC_SPI_MAXIMUM_BUFFER_SIZE; if (bus_attr->dma_enabled) { - err = spicommon_dma_chan_alloc(host_id, dma_chan); + err = spicommon_dma_chan_alloc(host_id, dma_chan, bus_config->dma_burst_size); if (err != ESP_OK) { goto cleanup; } diff --git a/components/esp_driver_spi/src/gpspi/spi_slave.c b/components/esp_driver_spi/src/gpspi/spi_slave.c index 3fba5572f6..1dc44fcf52 100644 --- a/components/esp_driver_spi/src/gpspi/spi_slave.c +++ b/components/esp_driver_spi/src/gpspi/spi_slave.c @@ -186,7 +186,7 @@ esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *b spihost[host]->bus_attr->dma_enabled = (dma_chan != SPI_DMA_DISABLED); spihost[host]->bus_attr->max_transfer_sz = SOC_SPI_MAXIMUM_BUFFER_SIZE; if (spihost[host]->bus_attr->dma_enabled) { - ret = spicommon_dma_chan_alloc(host, dma_chan); + ret = spicommon_dma_chan_alloc(host, dma_chan, bus_config->dma_burst_size); if (ret != ESP_OK) { goto cleanup; } diff --git a/components/esp_driver_spi/src/gpspi/spi_slave_hd.c b/components/esp_driver_spi/src/gpspi/spi_slave_hd.c index be9d510c5c..b805ee1576 100644 --- a/components/esp_driver_spi/src/gpspi/spi_slave_hd.c +++ b/components/esp_driver_spi/src/gpspi/spi_slave_hd.c @@ -127,7 +127,7 @@ esp_err_t spi_slave_hd_init(spi_host_device_t host_id, const spi_bus_config_t *b host->bus_attr = (spi_bus_attr_t *)spi_bus_get_attr(host_id); host->cs_io_num = config->spics_io_num; - ret = spicommon_dma_chan_alloc(host_id, config->dma_chan); + ret = spicommon_dma_chan_alloc(host_id, config->dma_chan, bus_config->dma_burst_size); if (ret != ESP_OK) { goto cleanup; } diff --git a/components/esp_hal_dma/esp32c5/include/hal/gdma_ll.h b/components/esp_hal_dma/esp32c5/include/hal/gdma_ll.h index 9a759a5d57..b2322d248c 100644 --- a/components/esp_hal_dma/esp32c5/include/hal/gdma_ll.h +++ b/components/esp_hal_dma/esp32c5/include/hal/gdma_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 */ @@ -18,6 +18,10 @@ #define GDMA_LL_AHB_BURST_SIZE_ADJUSTABLE 1 // AHB GDMA supports adjustable burst size #define GDMA_LL_MAX_BURST_SIZE_PSRAM 32 // PSRAM controller doesn't support burst access with size > 32 bytes +// GDMA supported burst sizes +#define GDMA_LL_SUPPORTED_BURST_SIZES_ARRAY { 4, 16, 32, 64 } +#define GDMA_LL_SUPPORTED_BURST_SIZES_STR "4, 16, 32, 64" + #ifdef __cplusplus extern "C" { #endif diff --git a/components/esp_hal_dma/esp32c61/include/hal/gdma_ll.h b/components/esp_hal_dma/esp32c61/include/hal/gdma_ll.h index 9a759a5d57..37549310eb 100644 --- a/components/esp_hal_dma/esp32c61/include/hal/gdma_ll.h +++ b/components/esp_hal_dma/esp32c61/include/hal/gdma_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 */ @@ -18,6 +18,10 @@ #define GDMA_LL_AHB_BURST_SIZE_ADJUSTABLE 1 // AHB GDMA supports adjustable burst size #define GDMA_LL_MAX_BURST_SIZE_PSRAM 32 // PSRAM controller doesn't support burst access with size > 32 bytes +// SPI DMA supported burst sizes +#define GDMA_LL_SUPPORTED_BURST_SIZES_ARRAY { 4, 16, 32, 64 } +#define GDMA_LL_SUPPORTED_BURST_SIZES_STR "4, 16, 32, 64" + #ifdef __cplusplus extern "C" { #endif diff --git a/components/esp_hal_dma/esp32h4/include/hal/gdma_ll.h b/components/esp_hal_dma/esp32h4/include/hal/gdma_ll.h index f9c7127989..94072bc569 100644 --- a/components/esp_hal_dma/esp32h4/include/hal/gdma_ll.h +++ b/components/esp_hal_dma/esp32h4/include/hal/gdma_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 */ @@ -18,6 +18,10 @@ #define GDMA_LL_AHB_BURST_SIZE_ADJUSTABLE 1 // AHB GDMA supports adjustable burst size #define GDMA_LL_MAX_BURST_SIZE_PSRAM 64 // PSRAM support INCR16 +// SPI DMA supported burst sizes +#define GDMA_LL_SUPPORTED_BURST_SIZES_ARRAY { 4, 16, 32, 64 } +#define GDMA_LL_SUPPORTED_BURST_SIZES_STR "4, 16, 32, 64" + #ifdef __cplusplus extern "C" { #endif diff --git a/components/esp_hal_dma/esp32p4/include/hal/gdma_ll.h b/components/esp_hal_dma/esp32p4/include/hal/gdma_ll.h index 4d7d80f7ba..21cdf37880 100644 --- a/components/esp_hal_dma/esp32p4/include/hal/gdma_ll.h +++ b/components/esp_hal_dma/esp32p4/include/hal/gdma_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 */ @@ -71,6 +71,10 @@ #define GDMA_LL_AXI_M2M_CAPABLE_PAIR_MASK 0x07 // pair 0,1,2 are M2M capable +// SPI DMA supported burst sizes +#define GDMA_LL_SUPPORTED_BURST_SIZES_ARRAY { 8, 16, 32, 64, 128 } +#define GDMA_LL_SUPPORTED_BURST_SIZES_STR "8, 16, 32, 64, 128" + #define GDMA_LL_TX_ETM_EVENT_TABLE(group, chan, event) \ (uint32_t[2][GDMA_ETM_EVENT_MAX]){ \ { \ 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 b3680dda2f..52ddfe7b05 100644 --- a/components/esp_hal_dma/esp32s3/include/hal/gdma_ll.h +++ b/components/esp_hal_dma/esp32s3/include/hal/gdma_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -74,6 +74,10 @@ extern "C" { #define GDMA_LL_AHB_M2M_CAPABLE_PAIR_MASK 0x1F // pair 0,1,2,3,4 are M2M capable +// SPI DMA supported burst sizes +#define GDMA_LL_SUPPORTED_BURST_SIZES_ARRAY { 16, 32, 64 } +#define GDMA_LL_SUPPORTED_BURST_SIZES_STR "16, 32, 64" + ///////////////////////////////////// Common ///////////////////////////////////////// /** diff --git a/components/esp_hal_dma/esp32s31/include/hal/gdma_ll.h b/components/esp_hal_dma/esp32s31/include/hal/gdma_ll.h index 089a74167e..6052342b41 100644 --- a/components/esp_hal_dma/esp32s31/include/hal/gdma_ll.h +++ b/components/esp_hal_dma/esp32s31/include/hal/gdma_ll.h @@ -63,6 +63,10 @@ #define GDMA_LL_AXI_M2M_CAPABLE_PAIR_MASK 0x07 // pair 0,1,2 are M2M capable #define GDMA_LL_LP_AHB_M2M_CAPABLE_PAIR_MASK 0x03 // pair 0,1 are M2M capable +// SPI DMA supported burst sizes +#define GDMA_LL_SUPPORTED_BURST_SIZES_ARRAY { 8, 16, 32, 64, 128 } +#define GDMA_LL_SUPPORTED_BURST_SIZES_STR "8, 16, 32, 64, 128" + #define GDMA_LL_TX_ETM_EVENT_TABLE(group, chan, event) \ (uint32_t[GDMA_LL_INST_NUM][GDMA_ETM_EVENT_MAX]){ \ { \