Merge branch 'refactor/lcd_i80_gpio_config_v5.2' into 'release/v5.2'

Optimize RGB LCD IRAM usage (v5.2)

See merge request espressif/esp-idf!34126
This commit is contained in:
morris
2024-10-14 10:43:38 +08:00
6 changed files with 16 additions and 18 deletions

View File

@ -19,6 +19,7 @@ menu "LCD and Touch Panel"
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
default n
help
Ensure the LCD interrupt is IRAM-Safe by allowing the interrupt handler to be
@ -29,7 +30,6 @@ menu "LCD and Touch Panel"
config LCD_RGB_RESTART_IN_VSYNC
bool "Restart transmission in VSYNC"
default n
select GDMA_CTRL_FUNC_IN_IRAM # need to restart GDMA in the LCD ISR
help
Reset the GDMA channel every VBlank to stop permanent desyncs from happening.
Only need to enable it when in your application, the DMA can't deliver data

View File

@ -1,8 +1,9 @@
[mapping:esp_lcd_driver]
archive: libesp_lcd.a
[mapping:esp_lcd_gdma]
archive: libesp_hw_support.a
entries:
if LCD_RGB_ISR_IRAM_SAFE = y:
esp_lcd_common: lcd_com_mount_dma_data (noflash)
gdma: gdma_reset (noflash)
gdma: gdma_start (noflash)
[mapping:esp_lcd_hal]
archive: libhal.a

View File

@ -58,7 +58,7 @@ static esp_err_t i2s_lcd_init_dma_link(esp_lcd_i80_bus_handle_t bus);
static esp_err_t i2s_lcd_configure_gpio(esp_lcd_i80_bus_handle_t bus, const esp_lcd_i80_bus_config_t *bus_config);
static void i2s_lcd_trigger_quick_trans_done_event(esp_lcd_i80_bus_handle_t bus);
static void lcd_i80_switch_devices(lcd_panel_io_i80_t *cur_device, lcd_panel_io_i80_t *next_device);
static void lcd_default_isr_handler(void *args);
static void i2s_lcd_default_isr_handler(void *args);
static esp_err_t panel_io_i80_register_event_callbacks(esp_lcd_panel_io_handle_t io, const esp_lcd_panel_io_callbacks_t *cbs, void *user_ctx);
struct esp_lcd_i80_bus_t {
@ -175,7 +175,7 @@ esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lc
int isr_flags = LCD_I80_INTR_ALLOC_FLAGS | ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_LOWMED;
ret = esp_intr_alloc_intrstatus(lcd_periph_signals.buses[bus->bus_id].irq_id, isr_flags,
(uint32_t)i2s_ll_get_intr_status_reg(bus->hal.dev),
I2S_LL_EVENT_TX_EOF, lcd_default_isr_handler, bus, &bus->intr);
I2S_LL_EVENT_TX_EOF, i2s_lcd_default_isr_handler, bus, &bus->intr);
ESP_GOTO_ON_ERROR(ret, err, TAG, "install interrupt failed");
i2s_ll_enable_intr(bus->hal.dev, I2S_LL_EVENT_TX_EOF, false); // disable interrupt temporarily
i2s_ll_clear_intr_status(bus->hal.dev, I2S_LL_EVENT_TX_EOF); // clear pending interrupt
@ -604,7 +604,7 @@ static esp_err_t panel_io_i80_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, cons
xQueueSend(next_device->trans_queue, &trans_desc, portMAX_DELAY);
next_device->num_trans_inflight++;
// enable interrupt and go into isr handler, where we fetch the transactions from trans_queue and start it
// we will go into `lcd_default_isr_handler` almost at once, because the "trans done" event is active at the moment
// we will go into `i2s_lcd_default_isr_handler` almost at once, because the "trans done" event is active at the moment
esp_intr_enable(bus->intr);
return ESP_OK;
}
@ -709,7 +709,7 @@ static void lcd_i80_switch_devices(lcd_panel_io_i80_t *cur_device, lcd_panel_io_
bus->cur_device = next_device;
}
static IRAM_ATTR void lcd_default_isr_handler(void *args)
static IRAM_ATTR void i2s_lcd_default_isr_handler(void *args)
{
esp_lcd_i80_bus_t *bus = (esp_lcd_i80_bus_t *)args;
lcd_i80_trans_descriptor_t *trans_desc = NULL;

View File

@ -58,7 +58,7 @@ static esp_err_t lcd_i80_select_periph_clock(esp_lcd_i80_bus_handle_t bus, lcd_c
static esp_err_t lcd_i80_bus_configure_gpio(esp_lcd_i80_bus_handle_t bus, const esp_lcd_i80_bus_config_t *bus_config);
static void lcd_i80_switch_devices(lcd_panel_io_i80_t *cur_device, lcd_panel_io_i80_t *next_device);
static void lcd_start_transaction(esp_lcd_i80_bus_t *bus, lcd_i80_trans_descriptor_t *trans_desc);
static void lcd_default_isr_handler(void *args);
static void i80_lcd_default_isr_handler(void *args);
static esp_err_t panel_io_i80_register_event_callbacks(esp_lcd_panel_io_handle_t io, const esp_lcd_panel_io_callbacks_t *cbs, void *user_ctx);
struct esp_lcd_i80_bus_t {
@ -165,7 +165,7 @@ esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lc
int isr_flags = LCD_I80_INTR_ALLOC_FLAGS | ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_LOWMED;
ret = esp_intr_alloc_intrstatus(lcd_periph_signals.buses[bus_id].irq_id, isr_flags,
(uint32_t)lcd_ll_get_interrupt_status_reg(bus->hal.dev),
LCD_LL_EVENT_TRANS_DONE, lcd_default_isr_handler, bus, &bus->intr);
LCD_LL_EVENT_TRANS_DONE, i80_lcd_default_isr_handler, bus, &bus->intr);
ESP_GOTO_ON_ERROR(ret, err, TAG, "install interrupt failed");
lcd_ll_enable_interrupt(bus->hal.dev, LCD_LL_EVENT_TRANS_DONE, false); // disable all interrupts
lcd_ll_clear_interrupt_status(bus->hal.dev, UINT32_MAX); // clear pending interrupt
@ -503,7 +503,7 @@ static esp_err_t panel_io_i80_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, cons
xQueueSend(i80_device->trans_queue, &trans_desc, portMAX_DELAY);
i80_device->num_trans_inflight++;
// enable interrupt and go into isr handler, where we fetch the transactions from trans_queue and start it
// we will go into `lcd_default_isr_handler` almost at once, because the "trans done" event is active at the moment
// we will go into `i80_lcd_default_isr_handler` almost at once, because the "trans done" event is active at the moment
esp_intr_enable(bus->intr);
return ESP_OK;
}
@ -650,7 +650,7 @@ static void lcd_i80_switch_devices(lcd_panel_io_i80_t *cur_device, lcd_panel_io_
}
}
IRAM_ATTR static void lcd_default_isr_handler(void *args)
IRAM_ATTR static void i80_lcd_default_isr_handler(void *args)
{
esp_lcd_i80_bus_t *bus = (esp_lcd_i80_bus_t *)args;
lcd_i80_trans_descriptor_t *trans_desc = NULL;

View File

@ -79,7 +79,7 @@ static esp_err_t lcd_rgb_panel_select_clock_src(esp_rgb_panel_t *panel, lcd_cloc
static esp_err_t lcd_rgb_panel_create_trans_link(esp_rgb_panel_t *panel);
static esp_err_t lcd_rgb_panel_configure_gpio(esp_rgb_panel_t *panel, const esp_lcd_rgb_panel_config_t *panel_config);
static void lcd_rgb_panel_start_transmission(esp_rgb_panel_t *rgb_panel);
static void lcd_default_isr_handler(void *args);
static void rgb_lcd_default_isr_handler(void *args);
struct esp_rgb_panel_t {
esp_lcd_panel_t base; // Base class of generic lcd panel
@ -317,7 +317,7 @@ esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_conf
int isr_flags = LCD_RGB_INTR_ALLOC_FLAGS | ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_LOWMED;
ret = esp_intr_alloc_intrstatus(lcd_periph_signals.panels[panel_id].irq_id, isr_flags,
(uint32_t)lcd_ll_get_interrupt_status_reg(rgb_panel->hal.dev),
LCD_LL_EVENT_VSYNC_END, lcd_default_isr_handler, rgb_panel, &rgb_panel->intr);
LCD_LL_EVENT_VSYNC_END, rgb_lcd_default_isr_handler, rgb_panel, &rgb_panel->intr);
ESP_GOTO_ON_ERROR(ret, err, TAG, "install interrupt failed");
lcd_ll_enable_interrupt(rgb_panel->hal.dev, LCD_LL_EVENT_VSYNC_END, false); // disable all interrupts
lcd_ll_clear_interrupt_status(rgb_panel->hal.dev, UINT32_MAX); // clear pending interrupt
@ -1105,7 +1105,7 @@ IRAM_ATTR static void lcd_rgb_panel_try_update_pclk(esp_rgb_panel_t *rgb_panel)
portEXIT_CRITICAL_ISR(&rgb_panel->spinlock);
}
IRAM_ATTR static void lcd_default_isr_handler(void *args)
IRAM_ATTR static void rgb_lcd_default_isr_handler(void *args)
{
esp_rgb_panel_t *rgb_panel = (esp_rgb_panel_t *)args;
bool need_yield = false;

View File

@ -1,8 +1,5 @@
CONFIG_COMPILER_DUMP_RTL_FILES=y
CONFIG_LCD_RGB_ISR_IRAM_SAFE=y
CONFIG_GDMA_CTRL_FUNC_IN_IRAM=y
# bounce buffer mode relies on GDMA EOF interrupt to be service-able
CONFIG_GDMA_ISR_IRAM_SAFE=y
CONFIG_COMPILER_OPTIMIZATION_NONE=y
# silent the error check, as the error string are stored in rodata, causing RTL check failure
CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y