Merge branch 'refactor/gdma_set_iram_safe_in_runtime_v5.4' into 'release/v5.4'

refactor(gdma): use run-time iram-safe config (v5.4)

See merge request espressif/esp-idf!38459
This commit is contained in:
morris
2025-04-18 13:26:42 +08:00
32 changed files with 171 additions and 179 deletions

View File

@ -10,7 +10,7 @@ menu "ADC and ADC Calibration"
depends on SOC_ADC_DMA_SUPPORTED depends on SOC_ADC_DMA_SUPPORTED
bool "ADC continuous mode driver ISR IRAM-Safe" bool "ADC continuous mode driver ISR IRAM-Safe"
default n 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 help
Ensure the ADC continuous mode ISR is IRAM-Safe. When enabled, the ISR handler Ensure the ADC continuous mode ISR is IRAM-Safe. When enabled, the ISR handler
will be available when the cache is disabled. will be available when the cache is disabled.

View File

@ -30,6 +30,9 @@ esp_err_t adc_dma_init(adc_dma_t *adc_dma)
//alloc rx gdma channel //alloc rx gdma channel
gdma_channel_alloc_config_t rx_alloc_config = { gdma_channel_alloc_config_t rx_alloc_config = {
.direction = GDMA_CHANNEL_DIRECTION_RX, .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)); ret = gdma_new_ahb_channel(&rx_alloc_config, &(adc_dma->gdma_chan));
if (ret != ESP_OK) { if (ret != ESP_OK) {

View File

@ -23,5 +23,5 @@ entries:
if SOC_ADC_CALIBRATION_V1_SUPPORTED = y: if SOC_ADC_CALIBRATION_V1_SUPPORTED = y:
adc_hal_common: adc_hal_set_calibration_param (noflash) adc_hal_common: adc_hal_set_calibration_param (noflash)
adc_hal_common: adc_hal_calibration_init (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) adc_hal: adc_hal_get_reading_result (noflash)

View File

@ -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 #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" #include "esp_adc/adc_continuous.h"
/*--------------------------------------------------------------- /*---------------------------------------------------------------
ADC continuous work with cache safe ISR 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)); 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) static void IRAM_ATTR NOINLINE_ATTR s_test_cache_disable_period_us(test_adc_iram_ctx_t *ctx, uint32_t period_us)
{ {

View File

@ -36,17 +36,3 @@ def test_adc(dut: Dut) -> None:
) )
def test_adc_esp32c2_xtal_26mhz(dut: Dut) -> None: def test_adc_esp32c2_xtal_26mhz(dut: Dut) -> None:
dut.run_all_single_board_cases(timeout=120, reset=True) 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)

View File

@ -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

View File

@ -29,10 +29,8 @@ menu "ESP-Driver:Camera Controller Configurations"
bool "DVP ISR Cache-Safe" bool "DVP ISR Cache-Safe"
depends on SOC_LCDCAM_CAM_SUPPORTED depends on SOC_LCDCAM_CAM_SUPPORTED
default n default n
select DW_GDMA_ISR_IRAM_SAFE select GDMA_ISR_HANDLER_IN_IRAM if SOC_GDMA_SUPPORTED
select DW_GDMA_CTRL_FUNC_IN_IRAM select GDMA_CTRL_FUNC_IN_IRAM if SOC_GDMA_SUPPORTED
select DW_GDMA_SETTER_FUNC_IN_IRAM
select DW_GDMA_GETTER_FUNC_IN_IRAM
help help
Ensure the DVP driver ISR is Cache-Safe. When enabled, the ISR handler Ensure the DVP driver ISR is Cache-Safe. When enabled, the ISR handler
will be available when the cache is disabled. will be available when the cache is disabled.

View File

@ -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 = { gdma_channel_alloc_config_t rx_alloc_config = {
.direction = GDMA_CHANNEL_DIRECTION_RX, .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"); ESP_RETURN_ON_ERROR(esp_cache_get_alignment(MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA, &alignment_size), TAG, "failed to get cache alignment");

View File

@ -3,7 +3,7 @@ menu "ESP-Driver:I2S Configurations"
config I2S_ISR_IRAM_SAFE config I2S_ISR_IRAM_SAFE
bool "I2S ISR IRAM-Safe" bool "I2S ISR IRAM-Safe"
default n default n
select GDMA_ISR_IRAM_SAFE if SOC_GDMA_SUPPORTED select GDMA_ISR_HANDLER_IN_IRAM if SOC_GDMA_SUPPORTED
help help
Ensure the I2S interrupt is IRAM-Safe by allowing the interrupt handler to be 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). executable when the cache is disabled (e.g. SPI Flash write).

View File

@ -791,7 +791,11 @@ esp_err_t i2s_init_dma_intr(i2s_chan_handle_t handle, int intr_flag)
} }
/* Set GDMA config */ /* 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) { if (handle->dir == I2S_DIR_TX) {
dma_cfg.direction = GDMA_CHANNEL_DIRECTION_TX; dma_cfg.direction = GDMA_CHANNEL_DIRECTION_TX;
/* Register a new GDMA tx channel */ /* Register a new GDMA tx channel */

View File

@ -40,7 +40,7 @@ extern "C" {
// If ISR handler is allowed to run whilst cache is disabled, // 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 // 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_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) #define I2S_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
#else #else

View File

@ -11,6 +11,7 @@ menu "ESP-Driver:Parallel IO Configurations"
config PARLIO_ISR_IRAM_SAFE config PARLIO_ISR_IRAM_SAFE
bool "Parallel IO ISR IRAM-Safe" bool "Parallel IO ISR IRAM-Safe"
default n default n
select GDMA_ISR_HANDLER_IN_IRAM
select GDMA_CTRL_FUNC_IN_IRAM # the driver needs to start the GDMA in the interrupt select GDMA_CTRL_FUNC_IN_IRAM # the driver needs to start the GDMA in the interrupt
help help
Ensure the Parallel IO interrupt is IRAM-Safe by allowing the interrupt handler to be Ensure the Parallel IO interrupt is IRAM-Safe by allowing the interrupt handler to be

View File

@ -1,4 +1,4 @@
[mapping:parlio_driver_gdma] [mapping:parlio_driver_gdma_link]
archive: libesp_hw_support.a archive: libesp_hw_support.a
entries: entries:
if PARLIO_ISR_IRAM_SAFE: if PARLIO_ISR_IRAM_SAFE:

View File

@ -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 */ /* Allocate and connect the GDMA channel */
gdma_channel_alloc_config_t dma_chan_config = { gdma_channel_alloc_config_t dma_chan_config = {
.direction = GDMA_CHANNEL_DIRECTION_RX, .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"); 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)); 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); ESP_RETURN_ON_FALSE(payload_size >= 2 * alignment, ESP_ERR_INVALID_ARG, TAG, "The payload size should greater than %"PRIu32, 2 * alignment);
} }
#endif #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"); ESP_RETURN_ON_FALSE(esp_ptr_internal(payload), ESP_ERR_INVALID_ARG, TAG, "payload not in internal RAM");
#else #else
ESP_RETURN_ON_FALSE(recv_cfg->flags.indirect_mount || esp_ptr_internal(payload), ESP_ERR_INVALID_ARG, TAG, "payload not in internal RAM"); ESP_RETURN_ON_FALSE(recv_cfg->flags.indirect_mount || esp_ptr_internal(payload), ESP_ERR_INVALID_ARG, TAG, "payload not in internal RAM");

View File

@ -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 = { gdma_channel_alloc_config_t dma_chan_config = {
.direction = GDMA_CHANNEL_DIRECTION_TX, .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"); 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)); gdma_connect(tx_unit->dma_chan, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_PARLIO, 0));

View File

@ -3,8 +3,8 @@ menu "ESP-Driver:RMT Configurations"
config RMT_ISR_IRAM_SAFE config RMT_ISR_IRAM_SAFE
bool "RMT ISR IRAM-Safe" bool "RMT ISR IRAM-Safe"
default n default n
select GDMA_ISR_IRAM_SAFE if SOC_RMT_SUPPORT_DMA # RMT basic functionality relies on GDMA callback 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 select GDMA_CTRL_FUNC_IN_IRAM if SOC_RMT_SUPPORT_DMA # RMT needs to restart the GDMA in the interrupt
help help
Ensure the RMT interrupt is IRAM-Safe by allowing the interrupt handler to be 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). executable when the cache is disabled (e.g. SPI Flash write).

View File

@ -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 = { gdma_channel_alloc_config_t dma_chan_config = {
.direction = GDMA_CHANNEL_DIRECTION_RX, .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"); 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 = { gdma_transfer_config_t transfer_cfg = {

View File

@ -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 = { gdma_channel_alloc_config_t dma_chan_config = {
.direction = GDMA_CHANNEL_DIRECTION_TX, .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"); 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 = { gdma_strategy_config_t gdma_strategy_conf = {

View File

@ -26,6 +26,7 @@ menu "ESP-Driver:SPI Configurations"
select HAL_SPI_MASTER_FUNC_IN_IRAM select HAL_SPI_MASTER_FUNC_IN_IRAM
select ESP_SPI_BUS_LOCK_ISR_FUNCS_IN_IRAM select ESP_SPI_BUS_LOCK_ISR_FUNCS_IN_IRAM
select GDMA_CTRL_FUNC_IN_IRAM if SOC_GDMA_SUPPORTED select GDMA_CTRL_FUNC_IN_IRAM if SOC_GDMA_SUPPORTED
select GDMA_ISR_HANDLER_IN_IRAM if SOC_GDMA_SUPPORTED
help help
Place the SPI master ISR in to IRAM to avoid possible cache miss. Place the SPI master ISR in to IRAM to avoid possible cache miss.
@ -54,6 +55,7 @@ menu "ESP-Driver:SPI Configurations"
default y default y
select HAL_SPI_SLAVE_FUNC_IN_IRAM select HAL_SPI_SLAVE_FUNC_IN_IRAM
select GDMA_CTRL_FUNC_IN_IRAM if SOC_GDMA_SUPPORTED select GDMA_CTRL_FUNC_IN_IRAM if SOC_GDMA_SUPPORTED
select GDMA_ISR_HANDLER_IN_IRAM if SOC_GDMA_SUPPORTED
help help
Place the SPI slave ISR in to IRAM to avoid possible cache miss. Place the SPI slave ISR in to IRAM to avoid possible cache miss.

View File

@ -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) { if (dma_chan == SPI_DMA_CH_AUTO) {
gdma_channel_alloc_config_t tx_alloc_config = { gdma_channel_alloc_config_t tx_alloc_config = {
.flags.reserve_sibling = 1, .flags.reserve_sibling = 1,
#if CONFIG_SPI_MASTER_ISR_IN_IRAM
.flags.isr_cache_safe = true,
#endif
.direction = GDMA_CHANNEL_DIRECTION_TX, .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"); 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 = { gdma_channel_alloc_config_t rx_alloc_config = {
.direction = GDMA_CHANNEL_DIRECTION_RX, .direction = GDMA_CHANNEL_DIRECTION_RX,
.sibling_chan = dma_ctx->tx_dma_chan, .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"); ESP_RETURN_ON_ERROR(SPI_GDMA_NEW_CHANNEL(&rx_alloc_config, &dma_ctx->rx_dma_chan), SPI_TAG, "alloc gdma rx failed");

View File

@ -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 * SPDX-License-Identifier: Apache-2.0
*/ */
#include <stdlib.h>
#include <string.h>
#include <sys/param.h>
#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 "../dma/gdma_priv.h"
#include "hal/cache_hal.h" #include "hal/cache_hal.h"
#include "hal/cache_ll.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_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"); ESP_RETURN_ON_FALSE(dma_chan && ability, ESP_ERR_INVALID_ARG, TAG, "invalid argument");

View File

@ -3,24 +3,46 @@ menu "GDMA Configurations"
config GDMA_CTRL_FUNC_IN_IRAM config GDMA_CTRL_FUNC_IN_IRAM
bool "Place GDMA control functions in IRAM" bool "Place GDMA control functions in IRAM"
default n default n
select GDMA_OBJ_DRAM_SAFE
help help
Place GDMA control functions (like start/stop/append/reset) into IRAM, 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. so that these functions can be IRAM-safe and able to be called in the other IRAM interrupt context.
config GDMA_ISR_IRAM_SAFE config GDMA_ISR_HANDLER_IN_IRAM
bool "GDMA ISR IRAM-Safe" 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 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 help
This will ensure the GDMA interrupt handler is IRAM-Safe, allow to avoid flash 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. cache misses, and also be able to run whilst the cache is disabled.
(e.g. SPI Flash write). (e.g. SPI Flash write).
If this option is enabled, ALL GDMA channel's ISR handlers should be placed in IRAM, which is a overkill.
config GDMA_ENABLE_DEBUG_LOG It's recommend to set the "isr_cache_safe" in the "gdma_channel_alloc_config_t".
bool "Enable debug log" Then other GDMA channels won't be influenced.
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.
endmenu # GDMA Configurations endmenu # GDMA Configurations
menu "DW_GDMA Configurations" menu "DW_GDMA Configurations"

View File

@ -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 * 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). * - We're not using a global spin lock, instead, we created different spin locks at different level (group, pair).
*/ */
#include <stdlib.h> #include "gdma_priv.h"
#include <string.h>
#include <sys/cdefs.h>
#include <sys/param.h>
#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 "esp_memory_utils.h" #include "esp_memory_utils.h"
#include "esp_flash_encrypt.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 #if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
#include "esp_private/gdma_sleep_retention.h" #include "esp_private/gdma_sleep_retention.h"
#endif #endif
static const char *TAG = "gdma";
#if !SOC_RCC_IS_INDEPENDENT #if !SOC_RCC_IS_INDEPENDENT
// Reset and Clock Control registers are mixing with other peripherals, so we need to use a critical section // 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() #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) 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; esp_err_t ret = ESP_OK;
gdma_tx_channel_t *alloc_tx_channel = NULL; gdma_tx_channel_t *alloc_tx_channel = NULL;
gdma_rx_channel_t *alloc_rx_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.pair = pair;
alloc_tx_channel->base.direction = GDMA_CHANNEL_DIRECTION_TX; alloc_tx_channel->base.direction = GDMA_CHANNEL_DIRECTION_TX;
alloc_tx_channel->base.periph_id = GDMA_INVALID_PERIPH_TRIG; 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 alloc_tx_channel->base.del = gdma_del_tx_channel; // set channel deletion function
*ret_chan = &alloc_tx_channel->base; // return the installed channel *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.pair = pair;
alloc_rx_channel->base.direction = GDMA_CHANNEL_DIRECTION_RX; alloc_rx_channel->base.direction = GDMA_CHANNEL_DIRECTION_RX;
alloc_rx_channel->base.periph_id = GDMA_INVALID_PERIPH_TRIG; 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 alloc_rx_channel->base.del = gdma_del_rx_channel; // set channel deletion function
*ret_chan = &alloc_rx_channel->base; // return the installed channel *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_hal_context_t *hal = &group->hal;
gdma_tx_channel_t *tx_chan = __containerof(dma_chan, gdma_tx_channel_t, base); gdma_tx_channel_t *tx_chan = __containerof(dma_chan, gdma_tx_channel_t, base);
#if CONFIG_GDMA_ISR_IRAM_SAFE if (dma_chan->flags.isr_cache_safe) {
if (cbs->on_trans_eof) { if (cbs->on_trans_eof) {
ESP_RETURN_ON_FALSE(esp_ptr_in_iram(cbs->on_trans_eof), ESP_ERR_INVALID_ARG, ESP_RETURN_ON_FALSE(esp_ptr_in_iram(cbs->on_trans_eof), ESP_ERR_INVALID_ARG,
TAG, "on_trans_eof not in IRAM"); 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 // lazy install interrupt service
ESP_RETURN_ON_ERROR(gdma_install_tx_interrupt(tx_chan), TAG, "install interrupt service failed"); 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_hal_context_t *hal = &group->hal;
gdma_rx_channel_t *rx_chan = __containerof(dma_chan, gdma_rx_channel_t, base); gdma_rx_channel_t *rx_chan = __containerof(dma_chan, gdma_rx_channel_t, base);
#if CONFIG_GDMA_ISR_IRAM_SAFE if (dma_chan->flags.isr_cache_safe) {
if (cbs->on_recv_eof) { if (cbs->on_recv_eof) {
ESP_RETURN_ON_FALSE(esp_ptr_in_iram(cbs->on_recv_eof), ESP_ERR_INVALID_ARG, ESP_RETURN_ON_FALSE(esp_ptr_in_iram(cbs->on_recv_eof), ESP_ERR_INVALID_ARG,
TAG, "on_recv_eof not in IRAM"); 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 // lazy install interrupt service
ESP_RETURN_ON_ERROR(gdma_install_rx_interrupt(rx_chan), TAG, "install interrupt service failed"); 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; gdma_hal_context_t *hal = &group->hal;
int pair_id = pair->pair_id; int pair_id = pair->pair_id;
// pre-alloc a interrupt handle, with handler disabled // 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 #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 #endif
intr_handle_t intr = NULL; 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, 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; gdma_hal_context_t *hal = &group->hal;
int pair_id = pair->pair_id; int pair_id = pair->pair_id;
// pre-alloc a interrupt handle, with handler disabled // 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 #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 #endif
intr_handle_t intr = NULL; 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, 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: err:
return ret; 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

View File

@ -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 * SPDX-License-Identifier: Apache-2.0
*/ */
#include <stdlib.h>
#include <string.h>
#include <sys/cdefs.h>
#include <sys/param.h>
#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 "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_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"); ESP_RETURN_ON_FALSE(dma_chan && config, ESP_ERR_INVALID_ARG, TAG, "invalid argument");

View File

@ -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 * SPDX-License-Identifier: Apache-2.0
*/ */
// #define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
#include <stdlib.h>
#include <sys/cdefs.h>
#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 "gdma_priv.h"
#include "esp_private/etm_interface.h"
#define ETM_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT #define ETM_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
static const char *TAG = "gdma-etm";
typedef struct gdma_etm_task_t { typedef struct gdma_etm_task_t {
esp_etm_task_t base; esp_etm_task_t base;
gdma_channel_t *chan; gdma_channel_t *chan;

View File

@ -17,7 +17,7 @@
#include "hal/cache_ll.h" #include "hal/cache_ll.h"
#include "esp_cache.h" #include "esp_cache.h"
static const char *TAG = "gdma"; static const char *TAG = "gdma-link";
#if SOC_NON_CACHEABLE_OFFSET #if SOC_NON_CACHEABLE_OFFSET
#define GDMA_CACHE_ADDR_TO_NON_CACHE_ADDR(addr) ((addr) + SOC_NON_CACHEABLE_OFFSET) #define GDMA_CACHE_ADDR_TO_NON_CACHE_ADDR(addr) ((addr) + SOC_NON_CACHEABLE_OFFSET)

View File

@ -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 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -7,33 +7,44 @@
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/cdefs.h>
#include <sys/param.h>
#include "sdkconfig.h" #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/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_err.h" #include "esp_err.h"
#include "esp_log.h"
#include "esp_check.h"
#include "esp_intr_alloc.h" #include "esp_intr_alloc.h"
#include "esp_heap_caps.h" #include "esp_heap_caps.h"
#include "soc/soc_caps.h"
#include "hal/gdma_hal.h" #include "hal/gdma_hal.h"
#include "hal/gdma_ll.h" #include "hal/gdma_ll.h"
#include "hal/gdma_hal_ahb.h" #include "hal/gdma_hal_ahb.h"
#include "hal/gdma_hal_axi.h" #include "hal/gdma_hal_axi.h"
#include "soc/gdma_periph.h" #include "soc/gdma_periph.h"
#include "soc/periph_defs.h"
#include "esp_private/gdma.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) #define GDMA_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
#else #else
#define GDMA_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT #define GDMA_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
#endif #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 */ #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 #ifdef __cplusplus
extern "C" { extern "C" {
#endif #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` 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 { struct {
uint32_t start_stop_by_etm: 1; // whether the channel is started/stopped by ETM 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; } flags;
}; };

View File

@ -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 * SPDX-License-Identifier: Apache-2.0
*/ */
#include <stdlib.h> #include "gdma_priv.h"
#include <string.h>
#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 "esp_private/sleep_retention.h" #include "esp_private/sleep_retention.h"
#include "esp_private/esp_regdma.h" #include "esp_private/esp_regdma.h"
static const char *TAG = "gdma";
typedef struct { typedef struct {
int group_id; int group_id;
int pair_id; int pair_id;

View File

@ -31,6 +31,7 @@ typedef struct {
gdma_channel_direction_t direction; /*!< DMA channel direction */ gdma_channel_direction_t direction; /*!< DMA channel direction */
struct { 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 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; } flags;
} gdma_channel_alloc_config_t; } gdma_channel_alloc_config_t;

View File

@ -1,8 +1,7 @@
[mapping:gdma_driver] [mapping:gdma_driver]
archive: libesp_hw_support.a archive: libesp_hw_support.a
entries: entries:
# performance optimization, always put the DMA default interrupt handler in IRAM if GDMA_ISR_HANDLER_IN_IRAM = y:
if SOC_GDMA_SUPPORTED = y:
gdma: gdma_default_tx_isr (noflash) gdma: gdma_default_tx_isr (noflash)
gdma: gdma_default_rx_isr (noflash) gdma: gdma_default_rx_isr (noflash)

View File

@ -9,7 +9,7 @@ menu "ESP-Driver:LCD Controller Configurations"
if SOC_LCD_RGB_SUPPORTED if SOC_LCD_RGB_SUPPORTED
config LCD_RGB_ISR_IRAM_SAFE config LCD_RGB_ISR_IRAM_SAFE
bool "RGB LCD 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 default n
help help
Ensure the LCD interrupt is IRAM-Safe by allowing the interrupt handler to be Ensure the LCD interrupt is IRAM-Safe by allowing the interrupt handler to be

View File

@ -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 // alloc DMA channel and connect to LCD peripheral
gdma_channel_alloc_config_t dma_chan_config = { gdma_channel_alloc_config_t dma_chan_config = {
.direction = GDMA_CHANNEL_DIRECTION_TX, .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"); 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)); gdma_connect(rgb_panel->dma_chan, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_LCD, 0));