From 611fb654ce44966c6e24f1e08d47ac0bc60adf19 Mon Sep 17 00:00:00 2001 From: morris Date: Sat, 21 Sep 2024 23:02:27 +0800 Subject: [PATCH] refactor(lcd): clean up GPIO initialization --- .../include/esp_private/gpio.h | 11 +++ components/esp_driver_gpio/src/gpio.c | 2 +- components/esp_lcd/Kconfig | 2 +- components/esp_lcd/i80/esp_lcd_panel_io_i2s.c | 30 ++++---- components/esp_lcd/i80/esp_lcd_panel_io_i80.c | 69 +++++++++---------- components/esp_lcd/include/esp_lcd_io_i80.h | 2 +- components/esp_lcd/linker.lf | 7 +- .../esp_lcd/priv_include/esp_lcd_common.h | 2 + components/esp_lcd/rgb/esp_lcd_panel_rgb.c | 38 +++++----- .../test_apps/rgb_lcd/sdkconfig.ci.iram_safe | 3 - 10 files changed, 81 insertions(+), 85 deletions(-) diff --git a/components/esp_driver_gpio/include/esp_private/gpio.h b/components/esp_driver_gpio/include/esp_private/gpio.h index b2186295c0..2e06192f63 100644 --- a/components/esp_driver_gpio/include/esp_private/gpio.h +++ b/components/esp_driver_gpio/include/esp_private/gpio.h @@ -52,6 +52,17 @@ esp_err_t gpio_sleep_pupd_config_unapply(gpio_num_t gpio_num); */ esp_err_t gpio_func_sel(gpio_num_t gpio_num, uint32_t func); +/** + * @brief Enable output for an IO + * + * @param gpio_num GPIO number + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG GPIO number error + */ +esp_err_t gpio_output_enable(gpio_num_t gpio_num); + /** * @brief Disable output for an IO * diff --git a/components/esp_driver_gpio/src/gpio.c b/components/esp_driver_gpio/src/gpio.c index cffca8e8e8..a63ab11375 100644 --- a/components/esp_driver_gpio/src/gpio.c +++ b/components/esp_driver_gpio/src/gpio.c @@ -211,7 +211,7 @@ esp_err_t gpio_output_disable(gpio_num_t gpio_num) return ESP_OK; } -static esp_err_t gpio_output_enable(gpio_num_t gpio_num) +esp_err_t gpio_output_enable(gpio_num_t gpio_num) { GPIO_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "GPIO output gpio_num error", ESP_ERR_INVALID_ARG); gpio_hal_matrix_out_default(gpio_context.gpio_hal, gpio_num); // No peripheral output signal routed to the pin, just as a simple GPIO output diff --git a/components/esp_lcd/Kconfig b/components/esp_lcd/Kconfig index 1e6ee9407c..76d9aaa8ae 100644 --- a/components/esp_lcd/Kconfig +++ b/components/esp_lcd/Kconfig @@ -12,6 +12,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 @@ -22,7 +23,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 diff --git a/components/esp_lcd/i80/esp_lcd_panel_io_i2s.c b/components/esp_lcd/i80/esp_lcd_panel_io_i2s.c index 0851381033..e5cbf45a65 100644 --- a/components/esp_lcd/i80/esp_lcd_panel_io_i2s.c +++ b/components/esp_lcd/i80/esp_lcd_panel_io_i2s.c @@ -39,14 +39,12 @@ #include "esp_private/periph_ctrl.h" #include "esp_private/i2s_platform.h" #include "esp_private/gdma_link.h" +#include "esp_private/gpio.h" #include "soc/lcd_periph.h" #include "hal/i2s_hal.h" #include "hal/i2s_ll.h" #include "hal/i2s_types.h" -// the DMA descriptor used by esp32 and esp32s2, each descriptor can carry 4095 bytes at most -#define LCD_DMA_DESCRIPTOR_BUFFER_MAX_SIZE 4095 - static const char *TAG = "lcd_panel.io.i80"; typedef struct esp_lcd_i80_bus_t esp_lcd_i80_bus_t; @@ -61,7 +59,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 { @@ -188,7 +186,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_i2s_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 @@ -317,8 +315,8 @@ esp_err_t esp_lcd_new_panel_io_i80(esp_lcd_i80_bus_handle_t bus, const esp_lcd_p if (io_config->cs_gpio_num >= 0) { // CS signal is controlled by software gpio_set_level(io_config->cs_gpio_num, !io_config->flags.cs_active_high); // de-assert by default - gpio_set_direction(io_config->cs_gpio_num, GPIO_MODE_OUTPUT); - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[io_config->cs_gpio_num], PIN_FUNC_GPIO); + gpio_func_sel(io_config->cs_gpio_num, PIN_FUNC_GPIO); + gpio_output_enable(io_config->cs_gpio_num); } *ret_io = &(i80_device->base); ESP_LOGD(TAG, "new i80 lcd panel io @%p on bus(%d), pclk=%"PRIu32"Hz", i80_device, bus->bus_id, i80_device->pclk_hz); @@ -362,9 +360,8 @@ static esp_err_t panel_io_i80_del(esp_lcd_panel_io_t *io) LIST_REMOVE(i80_device, device_list_entry); portEXIT_CRITICAL(&bus->spinlock); - // reset CS GPIO if (i80_device->cs_gpio_num >= 0) { - gpio_reset_pin(i80_device->cs_gpio_num); + gpio_output_disable(i80_device->cs_gpio_num); } ESP_LOGD(TAG, "del i80 lcd panel io @%p", i80_device); @@ -648,7 +645,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; } @@ -698,21 +695,20 @@ static esp_err_t i2s_lcd_configure_gpio(esp_lcd_i80_bus_handle_t bus, const esp_ // connect peripheral signals via GPIO matrix // data line for (size_t i = 0; i < bus_config->bus_width; i++) { - gpio_set_direction(bus_config->data_gpio_nums[i], GPIO_MODE_OUTPUT); + gpio_func_sel(bus_config->data_gpio_nums[i], PIN_FUNC_GPIO); + // the esp_rom_gpio_connect_out_signal function will also help enable the output path properly #if SOC_I2S_TRANS_SIZE_ALIGN_WORD esp_rom_gpio_connect_out_signal(bus_config->data_gpio_nums[i], lcd_periph_i2s_signals.buses[bus_id].data_sigs[i + 8], false, false); #else esp_rom_gpio_connect_out_signal(bus_config->data_gpio_nums[i], lcd_periph_i2s_signals.buses[bus_id].data_sigs[i + SOC_I2S_MAX_DATA_WIDTH - bus_config->bus_width], false, false); #endif - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[bus_config->data_gpio_nums[i]], PIN_FUNC_GPIO); } // WR signal (pclk) - gpio_set_direction(bus_config->wr_gpio_num, GPIO_MODE_OUTPUT); + gpio_func_sel(bus_config->wr_gpio_num, PIN_FUNC_GPIO); esp_rom_gpio_connect_out_signal(bus_config->wr_gpio_num, lcd_periph_i2s_signals.buses[bus_id].wr_sig, true, false); - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[bus_config->wr_gpio_num], PIN_FUNC_GPIO); // DC signal is controlled by software, set as general purpose IO - gpio_set_direction(bus_config->dc_gpio_num, GPIO_MODE_OUTPUT); - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[bus_config->dc_gpio_num], PIN_FUNC_GPIO); + gpio_func_sel(bus_config->dc_gpio_num, PIN_FUNC_GPIO); + gpio_output_enable(bus_config->dc_gpio_num); return ESP_OK; } @@ -756,7 +752,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; diff --git a/components/esp_lcd/i80/esp_lcd_panel_io_i80.c b/components/esp_lcd/i80/esp_lcd_panel_io_i80.c index 96b8fb4ca8..d7a29f4450 100644 --- a/components/esp_lcd/i80/esp_lcd_panel_io_i80.c +++ b/components/esp_lcd/i80/esp_lcd_panel_io_i80.c @@ -43,8 +43,6 @@ #include "hal/cache_ll.h" #include "hal/cache_hal.h" -#define LCD_DMA_DESCRIPTOR_BUFFER_MAX_SIZE 4095 - #if defined(SOC_GDMA_TRIG_PERIPH_LCD0_BUS) && (SOC_GDMA_TRIG_PERIPH_LCD0_BUS == SOC_GDMA_BUS_AHB) #define LCD_GDMA_NEW_CHANNEL gdma_new_ahb_channel #define LCD_GDMA_DESCRIPTOR_ALIGN 4 @@ -76,7 +74,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 { @@ -157,18 +155,6 @@ esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lc // allocate i80 bus memory bus = heap_caps_calloc(1, sizeof(esp_lcd_i80_bus_t), LCD_I80_MEM_ALLOC_CAPS); ESP_GOTO_ON_FALSE(bus, ESP_ERR_NO_MEM, err, TAG, "no mem for i80 bus"); - size_t num_dma_nodes = bus_config->max_transfer_bytes / LCD_DMA_DESCRIPTOR_BUFFER_MAX_SIZE + 1; - // create DMA link list - gdma_link_list_config_t dma_link_config = { - .buffer_alignment = 1, // no special buffer alignment for LCD TX buffer - .item_alignment = LCD_GDMA_DESCRIPTOR_ALIGN, - .num_items = num_dma_nodes, - .flags = { - .check_owner = true, - }, - }; - ESP_GOTO_ON_ERROR(gdma_new_link_list(&dma_link_config, &bus->dma_link), err, TAG, "create DMA link list failed"); - bus->num_dma_nodes = num_dma_nodes; bus->bus_width = bus_config->bus_width; bus->bus_id = -1; // allocate the format buffer from internal memory, with DMA capability @@ -208,7 +194,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_i80_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 @@ -355,9 +341,10 @@ esp_err_t esp_lcd_new_panel_io_i80(esp_lcd_i80_bus_handle_t bus, const esp_lcd_p // we only configure the CS GPIO as output, don't connect to the peripheral signal at the moment // we will connect the CS GPIO to peripheral signal when switching devices in lcd_i80_switch_devices() if (io_config->cs_gpio_num >= 0) { - gpio_set_level(io_config->cs_gpio_num, !io_config->flags.cs_active_high); - gpio_set_direction(io_config->cs_gpio_num, GPIO_MODE_OUTPUT); + // CS signal is controlled by software + gpio_set_level(io_config->cs_gpio_num, !io_config->flags.cs_active_high); // de-assert by default gpio_func_sel(io_config->cs_gpio_num, PIN_FUNC_GPIO); + gpio_output_enable(io_config->cs_gpio_num); } *ret_io = &(i80_device->base); ESP_LOGD(TAG, "new i80 lcd panel io @%p on bus(%d)", i80_device, bus->bus_id); @@ -393,9 +380,8 @@ static esp_err_t panel_io_i80_del(esp_lcd_panel_io_t *io) LIST_REMOVE(i80_device, device_list_entry); portEXIT_CRITICAL(&bus->spinlock); - // reset CS to normal GPIO if (i80_device->cs_gpio_num >= 0) { - gpio_reset_pin(i80_device->cs_gpio_num); + gpio_output_disable(i80_device->cs_gpio_num); } ESP_LOGD(TAG, "del i80 lcd panel io @%p", i80_device); @@ -572,7 +558,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; } @@ -609,7 +595,7 @@ static esp_err_t lcd_i80_init_dma_link(esp_lcd_i80_bus_handle_t bus, const esp_l .direction = GDMA_CHANNEL_DIRECTION_TX, }; ret = LCD_GDMA_NEW_CHANNEL(&dma_chan_config, &bus->dma_chan); - ESP_GOTO_ON_ERROR(ret, err, TAG, "alloc DMA channel failed"); + ESP_RETURN_ON_ERROR(ret, TAG, "alloc DMA channel failed"); gdma_connect(bus->dma_chan, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_LCD, 0)); gdma_strategy_config_t strategy_config = { .auto_update_desc = true, @@ -621,14 +607,23 @@ static esp_err_t lcd_i80_init_dma_link(esp_lcd_i80_bus_handle_t bus, const esp_l .max_data_burst_size = bus_config->dma_burst_size ? bus_config->dma_burst_size : 16, // Enable DMA burst transfer for better performance .access_ext_mem = true, // the LCD can carry pixel buffer from the external memory }; - ESP_GOTO_ON_ERROR(gdma_config_transfer(bus->dma_chan, &trans_cfg), err, TAG, "config DMA transfer failed"); + ESP_RETURN_ON_ERROR(gdma_config_transfer(bus->dma_chan, &trans_cfg), TAG, "config DMA transfer failed"); gdma_get_alignment_constraints(bus->dma_chan, &bus->int_mem_align, &bus->ext_mem_align); + + size_t num_dma_nodes = bus_config->max_transfer_bytes / LCD_DMA_DESCRIPTOR_BUFFER_MAX_SIZE + 1; + // create DMA link list + gdma_link_list_config_t dma_link_config = { + .buffer_alignment = MAX(bus->int_mem_align, bus->ext_mem_align), + .item_alignment = LCD_GDMA_DESCRIPTOR_ALIGN, + .num_items = num_dma_nodes, + .flags = { + .check_owner = true, + }, + }; + ESP_RETURN_ON_ERROR(gdma_new_link_list(&dma_link_config, &bus->dma_link), TAG, "create DMA link list failed"); + bus->num_dma_nodes = num_dma_nodes; + return ESP_OK; -err: - if (bus->dma_chan) { - gdma_del_channel(bus->dma_chan); - } - return ret; } void *esp_lcd_i80_alloc_draw_buffer(esp_lcd_panel_io_handle_t io, size_t size, uint32_t caps) @@ -660,17 +655,18 @@ static esp_err_t lcd_i80_bus_configure_gpio(esp_lcd_i80_bus_handle_t bus, const // Set the number of output data lines lcd_ll_set_data_wire_width(bus->hal.dev, bus_config->bus_width); // connect peripheral signals via GPIO matrix + // data lines for (size_t i = 0; i < bus_config->bus_width; i++) { - gpio_set_direction(bus_config->data_gpio_nums[i], GPIO_MODE_OUTPUT); - esp_rom_gpio_connect_out_signal(bus_config->data_gpio_nums[i], lcd_periph_i80_signals.buses[bus_id].data_sigs[i], false, false); gpio_func_sel(bus_config->data_gpio_nums[i], PIN_FUNC_GPIO); + // the esp_rom_gpio_connect_out_signal function will also help enable the output path properly + esp_rom_gpio_connect_out_signal(bus_config->data_gpio_nums[i], lcd_periph_i80_signals.buses[bus_id].data_sigs[i], false, false); } - gpio_set_direction(bus_config->dc_gpio_num, GPIO_MODE_OUTPUT); - esp_rom_gpio_connect_out_signal(bus_config->dc_gpio_num, lcd_periph_i80_signals.buses[bus_id].dc_sig, false, false); + // D/C signal gpio_func_sel(bus_config->dc_gpio_num, PIN_FUNC_GPIO); - gpio_set_direction(bus_config->wr_gpio_num, GPIO_MODE_OUTPUT); - esp_rom_gpio_connect_out_signal(bus_config->wr_gpio_num, lcd_periph_i80_signals.buses[bus_id].wr_sig, false, false); + esp_rom_gpio_connect_out_signal(bus_config->dc_gpio_num, lcd_periph_i80_signals.buses[bus_id].dc_sig, false, false); + // WR signal (PCLK) gpio_func_sel(bus_config->wr_gpio_num, PIN_FUNC_GPIO); + esp_rom_gpio_connect_out_signal(bus_config->wr_gpio_num, lcd_periph_i80_signals.buses[bus_id].wr_sig, false, false); return ESP_OK; } @@ -722,8 +718,7 @@ static void lcd_i80_switch_devices(lcd_panel_io_i80_t *cur_device, lcd_panel_io_ lcd_ll_set_dc_level(bus->hal.dev, next_device->dc_levels.dc_idle_level, next_device->dc_levels.dc_cmd_level, next_device->dc_levels.dc_dummy_level, next_device->dc_levels.dc_data_level); if (cur_device && cur_device->cs_gpio_num >= 0) { - // disconnect current CS GPIO from peripheral signal - esp_rom_gpio_connect_out_signal(cur_device->cs_gpio_num, SIG_GPIO_OUT_IDX, false, false); + gpio_output_disable(cur_device->cs_gpio_num); } if (next_device->cs_gpio_num >= 0) { // connect CS signal to the new device @@ -733,7 +728,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; diff --git a/components/esp_lcd/include/esp_lcd_io_i80.h b/components/esp_lcd/include/esp_lcd_io_i80.h index 7b6bd90422..f2885390f5 100644 --- a/components/esp_lcd/include/esp_lcd_io_i80.h +++ b/components/esp_lcd/include/esp_lcd_io_i80.h @@ -30,7 +30,7 @@ typedef struct { size_t bus_width; /*!< Number of data lines, 8 or 16 */ size_t max_transfer_bytes; /*!< Maximum transfer size, this determines the length of internal DMA link */ union { - size_t psram_trans_align; /*!< DMA transfer alignment for data allocated from PSRAM */ + size_t psram_trans_align __attribute__((deprecated)); /*!< DMA transfer alignment for data allocated from PSRAM */ size_t dma_burst_size; /*!< DMA burst size, in bytes */ }; size_t sram_trans_align __attribute__((deprecated)); /*!< DMA transfer alignment for data allocated from SRAM */ diff --git a/components/esp_lcd/linker.lf b/components/esp_lcd/linker.lf index 6e3aa0d3cd..513429d536 100644 --- a/components/esp_lcd/linker.lf +++ b/components/esp_lcd/linker.lf @@ -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 diff --git a/components/esp_lcd/priv_include/esp_lcd_common.h b/components/esp_lcd/priv_include/esp_lcd_common.h index a7b8ae6161..b57d37a787 100644 --- a/components/esp_lcd/priv_include/esp_lcd_common.h +++ b/components/esp_lcd/priv_include/esp_lcd_common.h @@ -33,6 +33,8 @@ extern "C" { #define LCD_CLOCK_SRC_ATOMIC() #endif +#define LCD_DMA_DESCRIPTOR_BUFFER_MAX_SIZE 4095 + #if SOC_LCDCAM_SUPPORTED typedef enum { diff --git a/components/esp_lcd/rgb/esp_lcd_panel_rgb.c b/components/esp_lcd/rgb/esp_lcd_panel_rgb.c index 60165fc1c5..f105ddf7cc 100644 --- a/components/esp_lcd/rgb/esp_lcd_panel_rgb.c +++ b/components/esp_lcd/rgb/esp_lcd_panel_rgb.c @@ -28,17 +28,17 @@ #include "soc/soc_caps.h" #include "esp_clk_tree.h" #include "hal/dma_types.h" -#include "hal/gpio_hal.h" #include "esp_private/gdma.h" #include "driver/gpio.h" #include "esp_bit_defs.h" #include "esp_private/esp_clk_tree_common.h" #include "esp_private/periph_ctrl.h" +#include "esp_private/gpio.h" #include "esp_psram.h" #include "esp_lcd_common.h" #include "esp_memory_utils.h" #include "soc/lcd_periph.h" -#include "soc/soc_caps.h" +#include "soc/io_mux_reg.h" #include "hal/lcd_hal.h" #include "hal/lcd_ll.h" #include "hal/cache_hal.h" @@ -84,7 +84,7 @@ static esp_err_t lcd_rgb_create_dma_channel(esp_rgb_panel_t *panel); static void lcd_rgb_panel_init_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 @@ -336,7 +336,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_rgb_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 @@ -848,51 +848,45 @@ static esp_err_t rgb_panel_disp_on_off(esp_lcd_panel_t *panel, bool on_off) return ESP_OK; } -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 *rgb_panel, const esp_lcd_rgb_panel_config_t *panel_config) { - int panel_id = panel->panel_id; + int panel_id = rgb_panel->panel_id; // Set the number of output data lines - lcd_ll_set_data_wire_width(panel->hal.dev, panel_config->data_width); + lcd_ll_set_data_wire_width(rgb_panel->hal.dev, panel_config->data_width); // connect peripheral signals via GPIO matrix for (size_t i = 0; i < panel_config->data_width; i++) { if (panel_config->data_gpio_nums[i] >= 0) { - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[panel_config->data_gpio_nums[i]], PIN_FUNC_GPIO); - gpio_set_direction(panel_config->data_gpio_nums[i], GPIO_MODE_OUTPUT); + gpio_func_sel(panel_config->data_gpio_nums[i], PIN_FUNC_GPIO); esp_rom_gpio_connect_out_signal(panel_config->data_gpio_nums[i], lcd_periph_rgb_signals.panels[panel_id].data_sigs[i], false, false); } } if (panel_config->hsync_gpio_num >= 0) { - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[panel_config->hsync_gpio_num], PIN_FUNC_GPIO); - gpio_set_direction(panel_config->hsync_gpio_num, GPIO_MODE_OUTPUT); + gpio_func_sel(panel_config->hsync_gpio_num, PIN_FUNC_GPIO); esp_rom_gpio_connect_out_signal(panel_config->hsync_gpio_num, lcd_periph_rgb_signals.panels[panel_id].hsync_sig, false, false); } if (panel_config->vsync_gpio_num >= 0) { - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[panel_config->vsync_gpio_num], PIN_FUNC_GPIO); - gpio_set_direction(panel_config->vsync_gpio_num, GPIO_MODE_OUTPUT); + gpio_func_sel(panel_config->vsync_gpio_num, PIN_FUNC_GPIO); esp_rom_gpio_connect_out_signal(panel_config->vsync_gpio_num, lcd_periph_rgb_signals.panels[panel_id].vsync_sig, false, false); } // PCLK may not be necessary in some cases (i.e. VGA output) if (panel_config->pclk_gpio_num >= 0) { - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[panel_config->pclk_gpio_num], PIN_FUNC_GPIO); - gpio_set_direction(panel_config->pclk_gpio_num, GPIO_MODE_OUTPUT); + gpio_func_sel(panel_config->pclk_gpio_num, PIN_FUNC_GPIO); esp_rom_gpio_connect_out_signal(panel_config->pclk_gpio_num, lcd_periph_rgb_signals.panels[panel_id].pclk_sig, false, false); } // DE signal might not be necessary for some RGB LCD if (panel_config->de_gpio_num >= 0) { - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[panel_config->de_gpio_num], PIN_FUNC_GPIO); - gpio_set_direction(panel_config->de_gpio_num, GPIO_MODE_OUTPUT); + gpio_func_sel(panel_config->de_gpio_num, PIN_FUNC_GPIO); esp_rom_gpio_connect_out_signal(panel_config->de_gpio_num, lcd_periph_rgb_signals.panels[panel_id].de_sig, false, false); } - // disp enable GPIO is optional + // disp enable GPIO is optional, it is a general purpose output GPIO if (panel_config->disp_gpio_num >= 0) { - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[panel_config->disp_gpio_num], PIN_FUNC_GPIO); - gpio_set_direction(panel_config->disp_gpio_num, GPIO_MODE_OUTPUT); - esp_rom_gpio_connect_out_signal(panel_config->disp_gpio_num, SIG_GPIO_OUT_IDX, false, false); + gpio_func_sel(panel_config->disp_gpio_num, PIN_FUNC_GPIO); + gpio_output_enable(panel_config->disp_gpio_num); } return ESP_OK; } @@ -1147,7 +1141,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; diff --git a/components/esp_lcd/test_apps/rgb_lcd/sdkconfig.ci.iram_safe b/components/esp_lcd/test_apps/rgb_lcd/sdkconfig.ci.iram_safe index 0643ce8884..a0efad79df 100644 --- a/components/esp_lcd/test_apps/rgb_lcd/sdkconfig.ci.iram_safe +++ b/components/esp_lcd/test_apps/rgb_lcd/sdkconfig.ci.iram_safe @@ -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