refactor(drivers): refactor the iram-safe option of the gdma peripherals

Closes https://github.com/espressif/esp-idf/issues/15771
This commit is contained in:
morris
2025-04-14 18:19:36 +08:00
parent 7bcb7248bb
commit 2c376ff99f
22 changed files with 48 additions and 37 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

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