diff --git a/components/esp_adc/Kconfig b/components/esp_adc/Kconfig index 0bdf4dd73e..80ec475dbb 100644 --- a/components/esp_adc/Kconfig +++ b/components/esp_adc/Kconfig @@ -10,7 +10,7 @@ menu "ADC and ADC Calibration" depends on SOC_ADC_DMA_SUPPORTED bool "ADC continuous mode driver ISR IRAM-Safe" default n - select GDMA_ISR_IRAM_SAFE if SOC_ADC_DMA_SUPPORTED && SOC_GDMA_SUPPORTED + select GDMA_ISR_HANDLER_IN_IRAM if SOC_ADC_DMA_SUPPORTED && SOC_GDMA_SUPPORTED help Ensure the ADC continuous mode ISR is IRAM-Safe. When enabled, the ISR handler will be available when the cache is disabled. diff --git a/components/esp_adc/gdma/adc_dma.c b/components/esp_adc/gdma/adc_dma.c index ff5ef61933..21bc9431c4 100644 --- a/components/esp_adc/gdma/adc_dma.c +++ b/components/esp_adc/gdma/adc_dma.c @@ -30,6 +30,9 @@ esp_err_t adc_dma_init(adc_dma_t *adc_dma) //alloc rx gdma channel gdma_channel_alloc_config_t rx_alloc_config = { .direction = GDMA_CHANNEL_DIRECTION_RX, +#if CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE + .flags.isr_cache_safe = true, +#endif }; ret = gdma_new_ahb_channel(&rx_alloc_config, &(adc_dma->gdma_chan)); if (ret != ESP_OK) { diff --git a/components/esp_adc/linker.lf b/components/esp_adc/linker.lf index 24769b37a5..7c47533bf6 100644 --- a/components/esp_adc/linker.lf +++ b/components/esp_adc/linker.lf @@ -23,5 +23,5 @@ entries: if SOC_ADC_CALIBRATION_V1_SUPPORTED = y: adc_hal_common: adc_hal_set_calibration_param (noflash) adc_hal_common: adc_hal_calibration_init (noflash) - if ADC_CONTINUOUS_ISR_IRAM_SAFE = y || GDMA_ISR_IRAM_SAFE = y: + if ADC_CONTINUOUS_ISR_IRAM_SAFE = y: adc_hal: adc_hal_get_reading_result (noflash) diff --git a/components/esp_adc/test_apps/adc/main/test_adc_driver_iram.c b/components/esp_adc/test_apps/adc/main/test_adc_driver_iram.c index 59c86a6042..74a7517a05 100644 --- a/components/esp_adc/test_apps/adc/main/test_adc_driver_iram.c +++ b/components/esp_adc/test_apps/adc/main/test_adc_driver_iram.c @@ -142,7 +142,7 @@ TEST_CASE("ADC oneshot fast work with ISR and Flash", "[adc_oneshot]") } #endif //#if CONFIG_ADC_ONESHOT_CTRL_FUNC_IN_IRAM && CONFIG_GPTIMER_ISR_IRAM_SAFE -#if CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE || CONFIG_GDMA_ISR_IRAM_SAFE +#if CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE #include "esp_adc/adc_continuous.h" /*--------------------------------------------------------------- ADC continuous work with cache safe ISR @@ -249,7 +249,7 @@ TEST_CASE("ADC continuous work with ISR and Flash", "[adc_continuous]") TEST_ESP_OK(adc_continuous_deinit(handle)); } -#endif //#if CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE || CONFIG_GDMA_ISR_IRAM_SAFE +#endif //#if CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE static void IRAM_ATTR NOINLINE_ATTR s_test_cache_disable_period_us(test_adc_iram_ctx_t *ctx, uint32_t period_us) { diff --git a/components/esp_adc/test_apps/adc/pytest_adc.py b/components/esp_adc/test_apps/adc/pytest_adc.py index 94133182ae..3339a576f0 100644 --- a/components/esp_adc/test_apps/adc/pytest_adc.py +++ b/components/esp_adc/test_apps/adc/pytest_adc.py @@ -36,17 +36,3 @@ def test_adc(dut: Dut) -> None: ) def test_adc_esp32c2_xtal_26mhz(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=120, reset=True) - - -@pytest.mark.esp32s3 -@pytest.mark.esp32c3 -@pytest.mark.esp32c6 -@pytest.mark.esp32h2 -@pytest.mark.esp32c5 -@pytest.mark.esp32p4 -@pytest.mark.adc -@pytest.mark.parametrize('config', [ - 'gdma_iram_safe', -], indirect=True) -def test_adc_gdma_iram(dut: Dut) -> None: - dut.run_all_single_board_cases(timeout=120, reset=True) diff --git a/components/esp_adc/test_apps/adc/sdkconfig.ci.gdma_iram_safe b/components/esp_adc/test_apps/adc/sdkconfig.ci.gdma_iram_safe deleted file mode 100644 index 67db32cae0..0000000000 --- a/components/esp_adc/test_apps/adc/sdkconfig.ci.gdma_iram_safe +++ /dev/null @@ -1,7 +0,0 @@ -CONFIG_COMPILER_DUMP_RTL_FILES=y -CONFIG_GDMA_ISR_IRAM_SAFE=y -CONFIG_COMPILER_OPTIMIZATION_SIZE=y -# silent the error check, as the error string are stored in rodata, causing RTL check failure -CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y -CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y -CONFIG_HAL_ASSERTION_SILENT=y diff --git a/components/esp_driver_cam/Kconfig b/components/esp_driver_cam/Kconfig index e502c4dc39..e162894c33 100644 --- a/components/esp_driver_cam/Kconfig +++ b/components/esp_driver_cam/Kconfig @@ -29,10 +29,8 @@ menu "ESP-Driver:Camera Controller Configurations" bool "DVP ISR Cache-Safe" depends on SOC_LCDCAM_CAM_SUPPORTED default n - select DW_GDMA_ISR_IRAM_SAFE - select DW_GDMA_CTRL_FUNC_IN_IRAM - select DW_GDMA_SETTER_FUNC_IN_IRAM - select DW_GDMA_GETTER_FUNC_IN_IRAM + select GDMA_ISR_HANDLER_IN_IRAM if SOC_GDMA_SUPPORTED + select GDMA_CTRL_FUNC_IN_IRAM if SOC_GDMA_SUPPORTED help Ensure the DVP driver ISR is Cache-Safe. When enabled, the ISR handler will be available when the cache is disabled. diff --git a/components/esp_driver_cam/dvp/src/esp_cam_ctlr_dvp_gdma.c b/components/esp_driver_cam/dvp/src/esp_cam_ctlr_dvp_gdma.c index 4e428b2505..bb1ef35c6c 100644 --- a/components/esp_driver_cam/dvp/src/esp_cam_ctlr_dvp_gdma.c +++ b/components/esp_driver_cam/dvp/src/esp_cam_ctlr_dvp_gdma.c @@ -65,6 +65,9 @@ esp_err_t esp_cam_ctlr_dvp_dma_init(esp_cam_ctlr_dvp_dma_t *dma, uint32_t burst_ gdma_channel_alloc_config_t rx_alloc_config = { .direction = GDMA_CHANNEL_DIRECTION_RX, +#if CONFIG_CAM_CTLR_DVP_CAM_ISR_CACHE_SAFE + .flags.isr_cache_safe = true, +#endif }; ESP_RETURN_ON_ERROR(esp_cache_get_alignment(MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA, &alignment_size), TAG, "failed to get cache alignment"); diff --git a/components/esp_driver_i2s/Kconfig b/components/esp_driver_i2s/Kconfig index 919b6ec143..dc57c8c211 100644 --- a/components/esp_driver_i2s/Kconfig +++ b/components/esp_driver_i2s/Kconfig @@ -3,7 +3,7 @@ menu "ESP-Driver:I2S Configurations" config I2S_ISR_IRAM_SAFE bool "I2S ISR IRAM-Safe" default n - select GDMA_ISR_IRAM_SAFE if SOC_GDMA_SUPPORTED + select GDMA_ISR_HANDLER_IN_IRAM if SOC_GDMA_SUPPORTED help Ensure the I2S interrupt is IRAM-Safe by allowing the interrupt handler to be executable when the cache is disabled (e.g. SPI Flash write). diff --git a/components/esp_driver_i2s/i2s_common.c b/components/esp_driver_i2s/i2s_common.c index 7d2950aa1d..0b01fd5005 100644 --- a/components/esp_driver_i2s/i2s_common.c +++ b/components/esp_driver_i2s/i2s_common.c @@ -791,7 +791,11 @@ esp_err_t i2s_init_dma_intr(i2s_chan_handle_t handle, int intr_flag) } /* Set GDMA config */ - gdma_channel_alloc_config_t dma_cfg = {}; + gdma_channel_alloc_config_t dma_cfg = { +#if CONFIG_I2S_ISR_IRAM_SAFE + .flags.isr_cache_safe = true, +#endif + }; if (handle->dir == I2S_DIR_TX) { dma_cfg.direction = GDMA_CHANNEL_DIRECTION_TX; /* Register a new GDMA tx channel */ diff --git a/components/esp_driver_i2s/i2s_private.h b/components/esp_driver_i2s/i2s_private.h index e87032b47f..b875c08f0b 100644 --- a/components/esp_driver_i2s/i2s_private.h +++ b/components/esp_driver_i2s/i2s_private.h @@ -40,7 +40,7 @@ extern "C" { // If ISR handler is allowed to run whilst cache is disabled, // Make sure all the code and related variables used by the handler are in the SRAM -#if CONFIG_I2S_ISR_IRAM_SAFE || CONFIG_GDMA_ISR_IRAM_SAFE +#if CONFIG_I2S_ISR_IRAM_SAFE #define I2S_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_SHARED) #define I2S_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT) #else diff --git a/components/esp_driver_parlio/Kconfig b/components/esp_driver_parlio/Kconfig index e8f94f7189..028d2ead57 100644 --- a/components/esp_driver_parlio/Kconfig +++ b/components/esp_driver_parlio/Kconfig @@ -11,6 +11,7 @@ menu "ESP-Driver:Parallel IO Configurations" config PARLIO_ISR_IRAM_SAFE bool "Parallel IO ISR IRAM-Safe" default n + select GDMA_ISR_HANDLER_IN_IRAM select GDMA_CTRL_FUNC_IN_IRAM # the driver needs to start the GDMA in the interrupt help Ensure the Parallel IO interrupt is IRAM-Safe by allowing the interrupt handler to be diff --git a/components/esp_driver_parlio/linker.lf b/components/esp_driver_parlio/linker.lf index ecc7aa0372..73c73e9b5e 100644 --- a/components/esp_driver_parlio/linker.lf +++ b/components/esp_driver_parlio/linker.lf @@ -1,4 +1,4 @@ -[mapping:parlio_driver_gdma] +[mapping:parlio_driver_gdma_link] archive: libesp_hw_support.a entries: if PARLIO_ISR_IRAM_SAFE: diff --git a/components/esp_driver_parlio/src/parlio_rx.c b/components/esp_driver_parlio/src/parlio_rx.c index fc61332349..caef2ad7a3 100644 --- a/components/esp_driver_parlio/src/parlio_rx.c +++ b/components/esp_driver_parlio/src/parlio_rx.c @@ -476,6 +476,9 @@ static esp_err_t s_parlio_rx_unit_init_dma(parlio_rx_unit_handle_t rx_unit) /* Allocate and connect the GDMA channel */ gdma_channel_alloc_config_t dma_chan_config = { .direction = GDMA_CHANNEL_DIRECTION_RX, +#if CONFIG_PARLIO_ISR_IRAM_SAFE + .flags.isr_cache_safe = true, +#endif }; ESP_RETURN_ON_ERROR(PARLIO_GDMA_NEW_CHANNEL(&dma_chan_config, &rx_unit->dma_chan), TAG, "allocate RX DMA channel failed"); gdma_connect(rx_unit->dma_chan, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_PARLIO, 0)); @@ -974,7 +977,7 @@ esp_err_t parlio_rx_unit_receive(parlio_rx_unit_handle_t rx_unit, ESP_RETURN_ON_FALSE(payload_size >= 2 * alignment, ESP_ERR_INVALID_ARG, TAG, "The payload size should greater than %"PRIu32, 2 * alignment); } #endif -#if CONFIG_GDMA_ISR_IRAM_SAFE +#if CONFIG_PARLIO_ISR_IRAM_SAFE ESP_RETURN_ON_FALSE(esp_ptr_internal(payload), ESP_ERR_INVALID_ARG, TAG, "payload not in internal RAM"); #else ESP_RETURN_ON_FALSE(recv_cfg->flags.indirect_mount || esp_ptr_internal(payload), ESP_ERR_INVALID_ARG, TAG, "payload not in internal RAM"); diff --git a/components/esp_driver_parlio/src/parlio_tx.c b/components/esp_driver_parlio/src/parlio_tx.c index ca488632b8..e772a600d3 100644 --- a/components/esp_driver_parlio/src/parlio_tx.c +++ b/components/esp_driver_parlio/src/parlio_tx.c @@ -200,6 +200,9 @@ static esp_err_t parlio_tx_unit_init_dma(parlio_tx_unit_t *tx_unit, const parlio { gdma_channel_alloc_config_t dma_chan_config = { .direction = GDMA_CHANNEL_DIRECTION_TX, +#if CONFIG_PARLIO_ISR_IRAM_SAFE + .flags.isr_cache_safe = true, +#endif }; ESP_RETURN_ON_ERROR(PARLIO_GDMA_NEW_CHANNEL(&dma_chan_config, &tx_unit->dma_chan), TAG, "allocate TX DMA channel failed"); gdma_connect(tx_unit->dma_chan, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_PARLIO, 0)); diff --git a/components/esp_driver_rmt/Kconfig b/components/esp_driver_rmt/Kconfig index 48302fa2fb..e48ee2b9ed 100644 --- a/components/esp_driver_rmt/Kconfig +++ b/components/esp_driver_rmt/Kconfig @@ -3,8 +3,8 @@ menu "ESP-Driver:RMT Configurations" config RMT_ISR_IRAM_SAFE bool "RMT ISR IRAM-Safe" default n - select GDMA_ISR_IRAM_SAFE if SOC_RMT_SUPPORT_DMA # RMT basic functionality relies on GDMA callback - select GDMA_CTRL_FUNC_IN_IRAM if SOC_RMT_SUPPORT_DMA # RMT needs to restart the GDMA in the interrupt + select GDMA_ISR_HANDLER_IN_IRAM if SOC_RMT_SUPPORT_DMA # RMT basic functionality relies on GDMA callback + select GDMA_CTRL_FUNC_IN_IRAM if SOC_RMT_SUPPORT_DMA # RMT needs to restart the GDMA in the interrupt help Ensure the RMT interrupt is IRAM-Safe by allowing the interrupt handler to be executable when the cache is disabled (e.g. SPI Flash write). diff --git a/components/esp_driver_rmt/src/rmt_rx.c b/components/esp_driver_rmt/src/rmt_rx.c index a83e620410..c11ffb38b9 100644 --- a/components/esp_driver_rmt/src/rmt_rx.c +++ b/components/esp_driver_rmt/src/rmt_rx.c @@ -57,6 +57,9 @@ static esp_err_t rmt_rx_init_dma_link(rmt_rx_channel_t *rx_channel, const rmt_rx { gdma_channel_alloc_config_t dma_chan_config = { .direction = GDMA_CHANNEL_DIRECTION_RX, +#if CONFIG_RMT_ISR_IRAM_SAFE + .flags.isr_cache_safe = true, +#endif }; ESP_RETURN_ON_ERROR(gdma_new_ahb_channel(&dma_chan_config, &rx_channel->base.dma_chan), TAG, "allocate RX DMA channel failed"); gdma_transfer_config_t transfer_cfg = { diff --git a/components/esp_driver_rmt/src/rmt_tx.c b/components/esp_driver_rmt/src/rmt_tx.c index ad0f0d9e82..4017aea8ce 100644 --- a/components/esp_driver_rmt/src/rmt_tx.c +++ b/components/esp_driver_rmt/src/rmt_tx.c @@ -52,6 +52,9 @@ static esp_err_t rmt_tx_init_dma_link(rmt_tx_channel_t *tx_channel, const rmt_tx { gdma_channel_alloc_config_t dma_chan_config = { .direction = GDMA_CHANNEL_DIRECTION_TX, +#if CONFIG_RMT_ISR_IRAM_SAFE + .flags.isr_cache_safe = true, +#endif }; ESP_RETURN_ON_ERROR(gdma_new_ahb_channel(&dma_chan_config, &tx_channel->base.dma_chan), TAG, "allocate TX DMA channel failed"); gdma_strategy_config_t gdma_strategy_conf = { diff --git a/components/esp_driver_spi/Kconfig b/components/esp_driver_spi/Kconfig index 4a3a1e3abc..b7a4c029da 100644 --- a/components/esp_driver_spi/Kconfig +++ b/components/esp_driver_spi/Kconfig @@ -26,6 +26,7 @@ menu "ESP-Driver:SPI Configurations" select HAL_SPI_MASTER_FUNC_IN_IRAM select ESP_SPI_BUS_LOCK_ISR_FUNCS_IN_IRAM select GDMA_CTRL_FUNC_IN_IRAM if SOC_GDMA_SUPPORTED + select GDMA_ISR_HANDLER_IN_IRAM if SOC_GDMA_SUPPORTED help Place the SPI master ISR in to IRAM to avoid possible cache miss. @@ -54,6 +55,7 @@ menu "ESP-Driver:SPI Configurations" default y select HAL_SPI_SLAVE_FUNC_IN_IRAM select GDMA_CTRL_FUNC_IN_IRAM if SOC_GDMA_SUPPORTED + select GDMA_ISR_HANDLER_IN_IRAM if SOC_GDMA_SUPPORTED help Place the SPI slave ISR in to IRAM to avoid possible cache miss. diff --git a/components/esp_driver_spi/src/gpspi/spi_common.c b/components/esp_driver_spi/src/gpspi/spi_common.c index 3ce0a21463..3a96c9a70c 100644 --- a/components/esp_driver_spi/src/gpspi/spi_common.c +++ b/components/esp_driver_spi/src/gpspi/spi_common.c @@ -222,6 +222,9 @@ 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 .direction = GDMA_CHANNEL_DIRECTION_TX, }; ESP_RETURN_ON_ERROR(SPI_GDMA_NEW_CHANNEL(&tx_alloc_config, &dma_ctx->tx_dma_chan), SPI_TAG, "alloc gdma tx failed"); @@ -229,6 +232,9 @@ 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 }; ESP_RETURN_ON_ERROR(SPI_GDMA_NEW_CHANNEL(&rx_alloc_config, &dma_ctx->rx_dma_chan), SPI_TAG, "alloc gdma rx failed"); diff --git a/components/esp_hw_support/deprecated/gdma_legacy.c b/components/esp_hw_support/deprecated/gdma_legacy.c index f25dd2c8ab..313f99dce2 100644 --- a/components/esp_hw_support/deprecated/gdma_legacy.c +++ b/components/esp_hw_support/deprecated/gdma_legacy.c @@ -1,23 +1,13 @@ /* - * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include -#include "sdkconfig.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "esp_log.h" -#include "esp_check.h" #include "../dma/gdma_priv.h" #include "hal/cache_hal.h" #include "hal/cache_ll.h" -static const char *TAG = "gdma"; - esp_err_t gdma_set_transfer_ability(gdma_channel_handle_t dma_chan, const gdma_transfer_ability_t *ability) { ESP_RETURN_ON_FALSE(dma_chan && ability, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); diff --git a/components/esp_hw_support/dma/Kconfig.dma b/components/esp_hw_support/dma/Kconfig.dma index 5620926e3e..d95212df71 100644 --- a/components/esp_hw_support/dma/Kconfig.dma +++ b/components/esp_hw_support/dma/Kconfig.dma @@ -3,24 +3,46 @@ menu "GDMA Configurations" config GDMA_CTRL_FUNC_IN_IRAM bool "Place GDMA control functions in IRAM" default n + select GDMA_OBJ_DRAM_SAFE help Place GDMA control functions (like start/stop/append/reset) into IRAM, so that these functions can be IRAM-safe and able to be called in the other IRAM interrupt context. - config GDMA_ISR_IRAM_SAFE - bool "GDMA ISR IRAM-Safe" + config GDMA_ISR_HANDLER_IN_IRAM + bool "Place GDMA ISR handler in IRAM to reduce latency" + default y + select GDMA_OBJ_DRAM_SAFE + help + Place GDMA ISR handler functions in IRAM to reduce latency caused by cache miss. + + config GDMA_OBJ_DRAM_SAFE + bool default n + help + This will ensure the GDMA object is DRAM-Safe, allow to avoid external memory + cache misses, and also be accessible whilst the cache is disabled. + + config GDMA_ENABLE_DEBUG_LOG + bool "Force enable debug log" + default n + help + If enabled, GDMA driver component will: + 1. ignore the global logging settings + 2. compile all log messages into the binary + 3. set the runtime log level to VERBOSE + Please enable this option by caution, as it will increase the binary size. + + config GDMA_ISR_IRAM_SAFE + bool "GDMA ISR IRAM-Safe (Deprecated. Read Help!)" + default n + select GDMA_ISR_HANDLER_IN_IRAM help This will ensure the GDMA interrupt handler is IRAM-Safe, allow to avoid flash cache misses, and also be able to run whilst the cache is disabled. (e.g. SPI Flash write). - - config GDMA_ENABLE_DEBUG_LOG - bool "Enable debug log" - default n - help - Whether to enable the debug log message for GDMA driver. - Note that, this option only controls the GDMA driver log, won't affect other drivers. + If this option is enabled, ALL GDMA channel's ISR handlers should be placed in IRAM, which is a overkill. + It's recommend to set the "isr_cache_safe" in the "gdma_channel_alloc_config_t". + Then other GDMA channels won't be influenced. endmenu # GDMA Configurations menu "DW_GDMA Configurations" diff --git a/components/esp_hw_support/dma/gdma.c b/components/esp_hw_support/dma/gdma.c index 9dd760792a..f222e9817e 100644 --- a/components/esp_hw_support/dma/gdma.c +++ b/components/esp_hw_support/dma/gdma.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -26,33 +26,14 @@ * - We're not using a global spin lock, instead, we created different spin locks at different level (group, pair). */ -#include -#include -#include -#include -#include "sdkconfig.h" -#if CONFIG_GDMA_ENABLE_DEBUG_LOG -// The local log level must be defined before including esp_log.h -// Set the maximum log level for this source file -#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG -#endif -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "soc/soc_caps.h" -#include "soc/periph_defs.h" -#include "esp_log.h" -#include "esp_check.h" +#include "gdma_priv.h" #include "esp_memory_utils.h" #include "esp_flash_encrypt.h" -#include "esp_private/periph_ctrl.h" -#include "gdma_priv.h" #if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP #include "esp_private/gdma_sleep_retention.h" #endif -static const char *TAG = "gdma"; - #if !SOC_RCC_IS_INDEPENDENT // Reset and Clock Control registers are mixing with other peripherals, so we need to use a critical section #define GDMA_RCC_ATOMIC() PERIPH_RCC_ATOMIC() @@ -94,9 +75,6 @@ typedef struct { static esp_err_t do_allocate_gdma_channel(const gdma_channel_search_info_t *search_info, const gdma_channel_alloc_config_t *config, gdma_channel_handle_t *ret_chan) { -#if CONFIG_GDMA_ENABLE_DEBUG_LOG - esp_log_level_set(TAG, ESP_LOG_DEBUG); -#endif esp_err_t ret = ESP_OK; gdma_tx_channel_t *alloc_tx_channel = NULL; gdma_rx_channel_t *alloc_rx_channel = NULL; @@ -170,6 +148,12 @@ search_done: alloc_tx_channel->base.pair = pair; alloc_tx_channel->base.direction = GDMA_CHANNEL_DIRECTION_TX; alloc_tx_channel->base.periph_id = GDMA_INVALID_PERIPH_TRIG; + // for backward compatibility, `CONFIG_GDMA_ISR_IRAM_SAFE` can still force ALL GDMA ISRs to be cache safe +#if CONFIG_GDMA_ISR_IRAM_SAFE + alloc_tx_channel->base.flags.isr_cache_safe = true; +#else + alloc_tx_channel->base.flags.isr_cache_safe = config->flags.isr_cache_safe; +#endif alloc_tx_channel->base.del = gdma_del_tx_channel; // set channel deletion function *ret_chan = &alloc_tx_channel->base; // return the installed channel } @@ -180,6 +164,12 @@ search_done: alloc_rx_channel->base.pair = pair; alloc_rx_channel->base.direction = GDMA_CHANNEL_DIRECTION_RX; alloc_rx_channel->base.periph_id = GDMA_INVALID_PERIPH_TRIG; + // for backward compatibility, `CONFIG_GDMA_ISR_IRAM_SAFE` can still force ALL GDMA ISRs to be cache safe +#if CONFIG_GDMA_ISR_IRAM_SAFE + alloc_rx_channel->base.flags.isr_cache_safe = true; +#else + alloc_rx_channel->base.flags.isr_cache_safe = config->flags.isr_cache_safe; +#endif alloc_rx_channel->base.del = gdma_del_rx_channel; // set channel deletion function *ret_chan = &alloc_rx_channel->base; // return the installed channel } @@ -455,20 +445,20 @@ esp_err_t gdma_register_tx_event_callbacks(gdma_channel_handle_t dma_chan, gdma_ gdma_hal_context_t *hal = &group->hal; gdma_tx_channel_t *tx_chan = __containerof(dma_chan, gdma_tx_channel_t, base); -#if CONFIG_GDMA_ISR_IRAM_SAFE - if (cbs->on_trans_eof) { - ESP_RETURN_ON_FALSE(esp_ptr_in_iram(cbs->on_trans_eof), ESP_ERR_INVALID_ARG, - TAG, "on_trans_eof not in IRAM"); + if (dma_chan->flags.isr_cache_safe) { + if (cbs->on_trans_eof) { + ESP_RETURN_ON_FALSE(esp_ptr_in_iram(cbs->on_trans_eof), ESP_ERR_INVALID_ARG, + TAG, "on_trans_eof not in IRAM"); + } + if (cbs->on_descr_err) { + ESP_RETURN_ON_FALSE(esp_ptr_in_iram(cbs->on_descr_err), ESP_ERR_INVALID_ARG, + TAG, "on_descr_err not in IRAM"); + } + if (user_data) { + ESP_RETURN_ON_FALSE(esp_ptr_internal(user_data), ESP_ERR_INVALID_ARG, + TAG, "user context not in internal RAM"); + } } - if (cbs->on_descr_err) { - ESP_RETURN_ON_FALSE(esp_ptr_in_iram(cbs->on_descr_err), ESP_ERR_INVALID_ARG, - TAG, "on_descr_err not in IRAM"); - } - if (user_data) { - ESP_RETURN_ON_FALSE(esp_ptr_internal(user_data), ESP_ERR_INVALID_ARG, - TAG, "user context not in internal RAM"); - } -#endif // CONFIG_GDMA_ISR_IRAM_SAFE // lazy install interrupt service ESP_RETURN_ON_ERROR(gdma_install_tx_interrupt(tx_chan), TAG, "install interrupt service failed"); @@ -495,24 +485,24 @@ esp_err_t gdma_register_rx_event_callbacks(gdma_channel_handle_t dma_chan, gdma_ gdma_hal_context_t *hal = &group->hal; gdma_rx_channel_t *rx_chan = __containerof(dma_chan, gdma_rx_channel_t, base); -#if CONFIG_GDMA_ISR_IRAM_SAFE - if (cbs->on_recv_eof) { - ESP_RETURN_ON_FALSE(esp_ptr_in_iram(cbs->on_recv_eof), ESP_ERR_INVALID_ARG, - TAG, "on_recv_eof not in IRAM"); + if (dma_chan->flags.isr_cache_safe) { + if (cbs->on_recv_eof) { + ESP_RETURN_ON_FALSE(esp_ptr_in_iram(cbs->on_recv_eof), ESP_ERR_INVALID_ARG, + TAG, "on_recv_eof not in IRAM"); + } + if (cbs->on_descr_err) { + ESP_RETURN_ON_FALSE(esp_ptr_in_iram(cbs->on_descr_err), ESP_ERR_INVALID_ARG, + TAG, "on_descr_err not in IRAM"); + } + if (cbs->on_recv_done) { + ESP_RETURN_ON_FALSE(esp_ptr_in_iram(cbs->on_recv_done), ESP_ERR_INVALID_ARG, + TAG, "on_recv_done not in IRAM"); + } + if (user_data) { + ESP_RETURN_ON_FALSE(esp_ptr_internal(user_data), ESP_ERR_INVALID_ARG, + TAG, "user context not in internal RAM"); + } } - if (cbs->on_descr_err) { - ESP_RETURN_ON_FALSE(esp_ptr_in_iram(cbs->on_descr_err), ESP_ERR_INVALID_ARG, - TAG, "on_descr_err not in IRAM"); - } - if (cbs->on_recv_done) { - ESP_RETURN_ON_FALSE(esp_ptr_in_iram(cbs->on_recv_done), ESP_ERR_INVALID_ARG, - TAG, "on_recv_done not in IRAM"); - } - if (user_data) { - ESP_RETURN_ON_FALSE(esp_ptr_internal(user_data), ESP_ERR_INVALID_ARG, - TAG, "user context not in internal RAM"); - } -#endif // CONFIG_GDMA_ISR_IRAM_SAFE // lazy install interrupt service ESP_RETURN_ON_ERROR(gdma_install_rx_interrupt(rx_chan), TAG, "install interrupt service failed"); @@ -870,9 +860,12 @@ static esp_err_t gdma_install_rx_interrupt(gdma_rx_channel_t *rx_chan) gdma_hal_context_t *hal = &group->hal; int pair_id = pair->pair_id; // pre-alloc a interrupt handle, with handler disabled - int isr_flags = GDMA_INTR_ALLOC_FLAGS; + int isr_flags = ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_LOWMED; + if (rx_chan->base.flags.isr_cache_safe) { + isr_flags |= ESP_INTR_FLAG_IRAM; + } #if GDMA_LL_AHB_TX_RX_SHARE_INTERRUPT - isr_flags |= ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_LOWMED; + isr_flags |= ESP_INTR_FLAG_SHARED; #endif intr_handle_t intr = NULL; ret = esp_intr_alloc_intrstatus(gdma_periph_signals.groups[group->group_id].pairs[pair_id].rx_irq_id, isr_flags, @@ -899,9 +892,12 @@ static esp_err_t gdma_install_tx_interrupt(gdma_tx_channel_t *tx_chan) gdma_hal_context_t *hal = &group->hal; int pair_id = pair->pair_id; // pre-alloc a interrupt handle, with handler disabled - int isr_flags = GDMA_INTR_ALLOC_FLAGS; + int isr_flags = ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_LOWMED; + if (tx_chan->base.flags.isr_cache_safe) { + isr_flags |= ESP_INTR_FLAG_IRAM; + } #if GDMA_LL_AHB_TX_RX_SHARE_INTERRUPT - isr_flags |= ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_LOWMED; + isr_flags |= ESP_INTR_FLAG_SHARED; #endif intr_handle_t intr = NULL; ret = esp_intr_alloc_intrstatus(gdma_periph_signals.groups[group->group_id].pairs[pair_id].tx_irq_id, isr_flags, @@ -919,3 +915,11 @@ static esp_err_t gdma_install_tx_interrupt(gdma_tx_channel_t *tx_chan) err: return ret; } + +#if CONFIG_GDMA_ENABLE_DEBUG_LOG +__attribute__((constructor)) +static void gdma_override_default_log_level(void) +{ + esp_log_level_set(TAG, ESP_LOG_VERBOSE); +} +#endif diff --git a/components/esp_hw_support/dma/gdma_crc.c b/components/esp_hw_support/dma/gdma_crc.c index da7425d39d..0979f32703 100644 --- a/components/esp_hw_support/dma/gdma_crc.c +++ b/components/esp_hw_support/dma/gdma_crc.c @@ -1,29 +1,11 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include -#include -#include "sdkconfig.h" -#if CONFIG_GDMA_ENABLE_DEBUG_LOG -// The local log level must be defined before including esp_log.h -// Set the maximum log level for this source file -#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG -#endif -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "soc/soc_caps.h" -#include "soc/periph_defs.h" -#include "esp_log.h" -#include "esp_check.h" #include "gdma_priv.h" -static const char *TAG = "gdma"; - esp_err_t gdma_config_crc_calculator(gdma_channel_handle_t dma_chan, const gdma_crc_calculator_config_t *config) { ESP_RETURN_ON_FALSE(dma_chan && config, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); diff --git a/components/esp_hw_support/dma/gdma_etm.c b/components/esp_hw_support/dma/gdma_etm.c index 5749c1cc78..c0e9be8191 100644 --- a/components/esp_hw_support/dma/gdma_etm.c +++ b/components/esp_hw_support/dma/gdma_etm.c @@ -1,28 +1,14 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ -// #define LOG_LOCAL_LEVEL ESP_LOG_DEBUG - -#include -#include -#include "sdkconfig.h" -#include "esp_log.h" -#include "esp_check.h" -#include "esp_heap_caps.h" -#include "hal/gdma_hal.h" -#include "hal/gdma_ll.h" -#include "soc/gdma_periph.h" -#include "esp_private/gdma.h" -#include "esp_private/etm_interface.h" #include "gdma_priv.h" +#include "esp_private/etm_interface.h" #define ETM_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT -static const char *TAG = "gdma-etm"; - typedef struct gdma_etm_task_t { esp_etm_task_t base; gdma_channel_t *chan; diff --git a/components/esp_hw_support/dma/gdma_link.c b/components/esp_hw_support/dma/gdma_link.c index 29288decf1..6a3199ea91 100644 --- a/components/esp_hw_support/dma/gdma_link.c +++ b/components/esp_hw_support/dma/gdma_link.c @@ -17,7 +17,7 @@ #include "hal/cache_ll.h" #include "esp_cache.h" -static const char *TAG = "gdma"; +static const char *TAG = "gdma-link"; #if SOC_NON_CACHEABLE_OFFSET #define GDMA_CACHE_ADDR_TO_NON_CACHE_ADDR(addr) ((addr) + SOC_NON_CACHEABLE_OFFSET) diff --git a/components/esp_hw_support/dma/gdma_priv.h b/components/esp_hw_support/dma/gdma_priv.h index 600397be02..4c0d921a59 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-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -7,33 +7,44 @@ #pragma once #include +#include +#include +#include +#include #include "sdkconfig.h" +#if CONFIG_GDMA_ENABLE_DEBUG_LOG +// The local log level must be defined before including esp_log.h +// Set the maximum log level for gdma driver +#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE +#endif +#include "soc/soc_caps.h" #include "freertos/FreeRTOS.h" +#include "freertos/task.h" #include "esp_err.h" +#include "esp_log.h" +#include "esp_check.h" #include "esp_intr_alloc.h" #include "esp_heap_caps.h" -#include "soc/soc_caps.h" #include "hal/gdma_hal.h" #include "hal/gdma_ll.h" #include "hal/gdma_hal_ahb.h" #include "hal/gdma_hal_axi.h" #include "soc/gdma_periph.h" +#include "soc/periph_defs.h" #include "esp_private/gdma.h" +#include "esp_private/periph_ctrl.h" -#if CONFIG_GDMA_ISR_IRAM_SAFE || CONFIG_GDMA_CTRL_FUNC_IN_IRAM +#if CONFIG_GDMA_OBJ_DRAM_SAFE #define GDMA_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT) #else #define GDMA_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT #endif -#if CONFIG_GDMA_ISR_IRAM_SAFE -#define GDMA_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_INTRDISABLED) -#else -#define GDMA_INTR_ALLOC_FLAGS ESP_INTR_FLAG_INTRDISABLED -#endif - #define GDMA_ACCESS_ENCRYPTION_MEM_ALIGNMENT 16 /*!< The alignment of the memory and size when DMA accesses the encryption memory */ +///!< Logging settings +#define TAG "gdma" + #ifdef __cplusplus extern "C" { #endif @@ -74,6 +85,7 @@ struct gdma_channel_t { esp_err_t (*del)(gdma_channel_t *channel); // channel deletion function, it's polymorphic, see `gdma_del_tx_channel` or `gdma_del_rx_channel` struct { uint32_t start_stop_by_etm: 1; // whether the channel is started/stopped by ETM + uint32_t isr_cache_safe: 1; // whether the interrupt of this channel need to be cache safe } flags; }; diff --git a/components/esp_hw_support/dma/gdma_sleep_retention.c b/components/esp_hw_support/dma/gdma_sleep_retention.c index 98d53e46c9..7deb476dac 100644 --- a/components/esp_hw_support/dma/gdma_sleep_retention.c +++ b/components/esp_hw_support/dma/gdma_sleep_retention.c @@ -1,28 +1,13 @@ /* - * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include "sdkconfig.h" -#include "soc/gdma_periph.h" -#include "soc/soc_caps.h" - -#include "esp_err.h" -#if CONFIG_GDMA_ENABLE_DEBUG_LOG -// The local log level must be defined before including esp_log.h -// Set the maximum log level for this source file -#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG -#endif -#include "esp_log.h" -#include "esp_check.h" +#include "gdma_priv.h" #include "esp_private/sleep_retention.h" #include "esp_private/esp_regdma.h" -static const char *TAG = "gdma"; - typedef struct { int group_id; int pair_id; diff --git a/components/esp_hw_support/dma/include/esp_private/gdma.h b/components/esp_hw_support/dma/include/esp_private/gdma.h index 22868fa3bd..af595f7c62 100644 --- a/components/esp_hw_support/dma/include/esp_private/gdma.h +++ b/components/esp_hw_support/dma/include/esp_private/gdma.h @@ -31,6 +31,7 @@ typedef struct { gdma_channel_direction_t direction; /*!< DMA channel direction */ struct { 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 */ + int isr_cache_safe: 1; /*!< If set, DMA channel allocator would allocate interrupt in cache-safe region, and ISR is serviceable when cache is disabled */ } flags; } gdma_channel_alloc_config_t; diff --git a/components/esp_hw_support/dma/linker.lf b/components/esp_hw_support/dma/linker.lf index db6159eed1..0f3faf6cb3 100644 --- a/components/esp_hw_support/dma/linker.lf +++ b/components/esp_hw_support/dma/linker.lf @@ -1,8 +1,7 @@ [mapping:gdma_driver] archive: libesp_hw_support.a entries: - # performance optimization, always put the DMA default interrupt handler in IRAM - if SOC_GDMA_SUPPORTED = y: + if GDMA_ISR_HANDLER_IN_IRAM = y: gdma: gdma_default_tx_isr (noflash) gdma: gdma_default_rx_isr (noflash) diff --git a/components/esp_lcd/Kconfig b/components/esp_lcd/Kconfig index c247c58637..a53f8514a9 100644 --- a/components/esp_lcd/Kconfig +++ b/components/esp_lcd/Kconfig @@ -9,7 +9,7 @@ menu "ESP-Driver:LCD Controller Configurations" if SOC_LCD_RGB_SUPPORTED config LCD_RGB_ISR_IRAM_SAFE bool "RGB LCD ISR IRAM-Safe" - select GDMA_ISR_IRAM_SAFE # bounce buffer mode relies on GDMA EOF interrupt + select GDMA_ISR_HANDLER_IN_IRAM # bounce buffer mode relies on GDMA EOF interrupt default n help Ensure the LCD interrupt is IRAM-Safe by allowing the interrupt handler to be diff --git a/components/esp_lcd/rgb/esp_lcd_panel_rgb.c b/components/esp_lcd/rgb/esp_lcd_panel_rgb.c index fe4518faf0..72df1e8266 100644 --- a/components/esp_lcd/rgb/esp_lcd_panel_rgb.c +++ b/components/esp_lcd/rgb/esp_lcd_panel_rgb.c @@ -882,6 +882,9 @@ static esp_err_t lcd_rgb_create_dma_channel(esp_rgb_panel_t *rgb_panel) // alloc DMA channel and connect to LCD peripheral gdma_channel_alloc_config_t dma_chan_config = { .direction = GDMA_CHANNEL_DIRECTION_TX, +#if CONFIG_LCD_RGB_ISR_IRAM_SAFE + .flags.isr_cache_safe = true, +#endif }; ESP_RETURN_ON_ERROR(LCD_GDMA_NEW_CHANNEL(&dma_chan_config, &rgb_panel->dma_chan), TAG, "alloc DMA channel failed"); gdma_connect(rgb_panel->dma_chan, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_LCD, 0));