mirror of
https://github.com/espressif/esp-idf.git
synced 2025-07-30 02:37:19 +02:00
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:
@ -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.
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
|
@ -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
|
@ -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.
|
||||
|
@ -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");
|
||||
|
@ -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).
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -1,4 +1,4 @@
|
||||
[mapping:parlio_driver_gdma]
|
||||
[mapping:parlio_driver_gdma_link]
|
||||
archive: libesp_hw_support.a
|
||||
entries:
|
||||
if PARLIO_ISR_IRAM_SAFE:
|
||||
|
@ -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");
|
||||
|
@ -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));
|
||||
|
@ -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).
|
||||
|
@ -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 = {
|
||||
|
@ -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 = {
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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 <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 "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");
|
||||
|
@ -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"
|
||||
|
@ -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 <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 "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
|
||||
|
@ -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 <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"
|
||||
|
||||
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");
|
||||
|
@ -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 <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 "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;
|
||||
|
@ -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)
|
||||
|
@ -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 <stdint.h>
|
||||
#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 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;
|
||||
};
|
||||
|
||||
|
@ -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 <stdlib.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 "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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
Reference in New Issue
Block a user