mirror of
https://github.com/espressif/esp-idf.git
synced 2025-07-31 19:24:33 +02:00
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:
@@ -19,6 +19,7 @@ menu "LCD and Touch Panel"
|
|||||||
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
|
||||||
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
|
||||||
@@ -29,7 +30,6 @@ menu "LCD and Touch Panel"
|
|||||||
config LCD_RGB_RESTART_IN_VSYNC
|
config LCD_RGB_RESTART_IN_VSYNC
|
||||||
bool "Restart transmission in VSYNC"
|
bool "Restart transmission in VSYNC"
|
||||||
default n
|
default n
|
||||||
select GDMA_CTRL_FUNC_IN_IRAM # need to restart GDMA in the LCD ISR
|
|
||||||
help
|
help
|
||||||
Reset the GDMA channel every VBlank to stop permanent desyncs from happening.
|
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
|
Only need to enable it when in your application, the DMA can't deliver data
|
||||||
|
@@ -1,8 +1,9 @@
|
|||||||
[mapping:esp_lcd_driver]
|
[mapping:esp_lcd_gdma]
|
||||||
archive: libesp_lcd.a
|
archive: libesp_hw_support.a
|
||||||
entries:
|
entries:
|
||||||
if LCD_RGB_ISR_IRAM_SAFE = y:
|
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]
|
[mapping:esp_lcd_hal]
|
||||||
archive: libhal.a
|
archive: libhal.a
|
||||||
|
@@ -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 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 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_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);
|
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 {
|
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;
|
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,
|
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),
|
(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");
|
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_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
|
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);
|
xQueueSend(next_device->trans_queue, &trans_desc, portMAX_DELAY);
|
||||||
next_device->num_trans_inflight++;
|
next_device->num_trans_inflight++;
|
||||||
// enable interrupt and go into isr handler, where we fetch the transactions from trans_queue and start it
|
// 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);
|
esp_intr_enable(bus->intr);
|
||||||
return ESP_OK;
|
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;
|
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;
|
esp_lcd_i80_bus_t *bus = (esp_lcd_i80_bus_t *)args;
|
||||||
lcd_i80_trans_descriptor_t *trans_desc = NULL;
|
lcd_i80_trans_descriptor_t *trans_desc = NULL;
|
||||||
|
@@ -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 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_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_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);
|
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 {
|
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;
|
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,
|
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),
|
(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");
|
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_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
|
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);
|
xQueueSend(i80_device->trans_queue, &trans_desc, portMAX_DELAY);
|
||||||
i80_device->num_trans_inflight++;
|
i80_device->num_trans_inflight++;
|
||||||
// enable interrupt and go into isr handler, where we fetch the transactions from trans_queue and start it
|
// 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);
|
esp_intr_enable(bus->intr);
|
||||||
return ESP_OK;
|
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;
|
esp_lcd_i80_bus_t *bus = (esp_lcd_i80_bus_t *)args;
|
||||||
lcd_i80_trans_descriptor_t *trans_desc = NULL;
|
lcd_i80_trans_descriptor_t *trans_desc = NULL;
|
||||||
|
@@ -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_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 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_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 {
|
struct esp_rgb_panel_t {
|
||||||
esp_lcd_panel_t base; // Base class of generic lcd panel
|
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;
|
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,
|
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),
|
(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");
|
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_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
|
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);
|
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;
|
esp_rgb_panel_t *rgb_panel = (esp_rgb_panel_t *)args;
|
||||||
bool need_yield = false;
|
bool need_yield = false;
|
||||||
|
@@ -1,8 +1,5 @@
|
|||||||
CONFIG_COMPILER_DUMP_RTL_FILES=y
|
CONFIG_COMPILER_DUMP_RTL_FILES=y
|
||||||
CONFIG_LCD_RGB_ISR_IRAM_SAFE=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
|
CONFIG_COMPILER_OPTIMIZATION_NONE=y
|
||||||
# silent the error check, as the error string are stored in rodata, causing RTL check failure
|
# 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_CHECKS_SILENT=y
|
||||||
|
Reference in New Issue
Block a user