diff --git a/examples/peripherals/lcd/rgb_panel/README.md b/examples/peripherals/lcd/rgb_panel/README.md index 18974cd40c..b219e4207c 100644 --- a/examples/peripherals/lcd/rgb_panel/README.md +++ b/examples/peripherals/lcd/rgb_panel/README.md @@ -3,18 +3,17 @@ # RGB LCD Panel Example -[esp_lcd](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/lcd.html) supports RGB interfaced LCD panel, with one or two frame buffer(s) managed by the driver itself. +[esp_lcd](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/peripherals/lcd/rgb_lcd.html) supports RGB interfaced LCD panel, with multiple buffer modes. This example shows the general process of installing an RGB panel driver, and displays a scatter chart on the screen based on the LVGL library. -This example shows the general process of installing an RGB panel driver, and displays a scatter chart on the screen based on the LVGL library. +This example uses the [esp_timer](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/esp_timer.html) to generate the ticks needed by LVGL and uses a dedicated task to run the `lv_timer_handler()`. Since the LVGL APIs are not thread-safe, this example uses a mutex which be invoked before the call of `lv_timer_handler()` and released after it. The same mutex needs to be used in other tasks and threads around every LVGL (lv_...) related function call and code. For more porting guides, please refer to [LVGL Display porting reference](https://docs.lvgl.io/master/porting/display.html). -This example uses the [esp_timer](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/esp_timer.html) to generate the ticks needed by LVGL and uses a dedicated task to run the `lv_timer_handler()`. Since the LVGL APIs are not thread-safe, this example uses a mutex which be invoked before the call of `lv_timer_handler()` and released after it. The same mutex needs to be used in other tasks and threads around every LVGL (lv_...) related function call and code. For more porting guides, please refer to [LVGL porting doc](https://docs.lvgl.io/master/porting/index.html). +This example uses 3 kinds of **buffering mode**: -This example uses two kinds of **buffering mode** based on the number of frame buffers: - -| Number of Frame Buffers | LVGL buffering mode | Way to avoid tear effect | -|-------------------------|---------------------|-------------------------------------------------------------------------------------------------------------| -| 1 | Two buffers | Extra synchronization mechanism is needed, e.g. using semaphore. | -| 2 | Full refresh | There's no intersection between writing to an offline frame buffer and reading from an online frame buffer. | +| Driver Buffers | LVGL draw buffers | Pros and Cons | +|-----------------|---------------------|-----------------------------------------------------------------------------------| +| 1 Frame Buffer | Two partial buffers | fewest memory footprint, performance affected by memory copy | +| 2 Frame Buffers | Direct refresh mode | no extra memory copy between draw buffer and frame buffer, large memory cost | +| 1 Frame Buffer +
2 Bounce Buffers | Two partial buffers | Fast DMA read, high CPU usage, more internal memory cost | ## How to use the example @@ -114,7 +113,7 @@ I (926) example: Display LVGL Scatter Chart * Or adding an extra synchronization mechanism between writing (by Cache) and reading (by EDMA) the frame buffer. * Low PCLK frequency * Enable `CONFIG_EXAMPLE_USE_BOUNCE_BUFFER`, which will make the LCD controller fetch data from internal SRAM (instead of the PSRAM), but at the cost of increasing CPU usage. - * Enable `CONFIG_SPIRAM_FETCH_INSTRUCTIONS` and `CONFIG_SPIRAM_RODATA` can also help if the you're not using the bounce buffer mode. These two configurations can save some **SPI0** bandwidth from being consumed by ICache. + * Enable `CONFIG_SPIRAM_XIP_FROM_PSRAM` can also help if the you're not using the bounce buffer mode. These two configurations can save some **SPI0** bandwidth from being consumed by ICache. * Why the RGB timing is correct but the LCD doesn't show anything? * Please read the datasheet of the IC used by your LCD module, and check if it needs a special initialization sequence. The initialization is usually done by sending some specific SPI commands and parameters to the IC. After the initialization, the LCD will be ready to receive RGB data. For simplicity, this example only works out of the box for those LCD modules which don't need extra initialization. diff --git a/examples/peripherals/lcd/rgb_panel/main/idf_component.yml b/examples/peripherals/lcd/rgb_panel/main/idf_component.yml index 6d59bd0def..43f5954cfd 100644 --- a/examples/peripherals/lcd/rgb_panel/main/idf_component.yml +++ b/examples/peripherals/lcd/rgb_panel/main/idf_component.yml @@ -1,3 +1,2 @@ dependencies: - idf: ">=4.4" - lvgl/lvgl: "~8.3.0" + lvgl/lvgl: "^9.0.0" diff --git a/examples/peripherals/lcd/rgb_panel/main/lvgl_demo_ui.c b/examples/peripherals/lcd/rgb_panel/main/lvgl_demo_ui.c index 2ed988ceb3..b0ef9bcfa4 100644 --- a/examples/peripherals/lcd/rgb_panel/main/lvgl_demo_ui.c +++ b/examples/peripherals/lcd/rgb_panel/main/lvgl_demo_ui.c @@ -1,33 +1,36 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 */ -// This demo UI is adapted from LVGL official example: https://docs.lvgl.io/master/examples.html#scatter-chart +// This demo UI is adapted from LVGL official example: https://docs.lvgl.io/master/widgets/chart.html#scatter-chart #include "lvgl.h" static void draw_event_cb(lv_event_t *e) { - lv_obj_draw_part_dsc_t *dsc = lv_event_get_draw_part_dsc(e); - if (dsc->part == LV_PART_ITEMS) { + lv_draw_task_t *draw_task = lv_event_get_draw_task(e); + lv_draw_dsc_base_t *base_dsc = lv_draw_task_get_draw_dsc(draw_task); + if (base_dsc->part == LV_PART_INDICATOR) { lv_obj_t *obj = lv_event_get_target(e); lv_chart_series_t *ser = lv_chart_get_series_next(obj, NULL); + lv_draw_rect_dsc_t *rect_draw_dsc = lv_draw_task_get_draw_dsc(draw_task); uint32_t cnt = lv_chart_get_point_count(obj); + /*Make older value more transparent*/ - dsc->rect_dsc->bg_opa = (LV_OPA_COVER * dsc->id) / (cnt - 1); + rect_draw_dsc->bg_opa = (LV_OPA_COVER * base_dsc->id2) / (cnt - 1); /*Make smaller values blue, higher values red*/ - lv_coord_t *x_array = lv_chart_get_x_array(obj, ser); - lv_coord_t *y_array = lv_chart_get_y_array(obj, ser); + int32_t *x_array = lv_chart_get_x_array(obj, ser); + int32_t *y_array = lv_chart_get_y_array(obj, ser); /*dsc->id is the tells drawing order, but we need the ID of the point being drawn.*/ uint32_t start_point = lv_chart_get_x_start_point(obj, ser); - uint32_t p_act = (start_point + dsc->id) % cnt; /*Consider start point to get the index of the array*/ + uint32_t p_act = (start_point + base_dsc->id2) % cnt; /*Consider start point to get the index of the array*/ lv_opa_t x_opa = (x_array[p_act] * LV_OPA_50) / 200; lv_opa_t y_opa = (y_array[p_act] * LV_OPA_50) / 1000; - dsc->rect_dsc->bg_color = lv_color_mix(lv_palette_main(LV_PALETTE_RED), + rect_draw_dsc->bg_color = lv_color_mix(lv_palette_main(LV_PALETTE_RED), lv_palette_main(LV_PALETTE_BLUE), x_opa + y_opa); } @@ -35,24 +38,22 @@ static void draw_event_cb(lv_event_t *e) static void add_data(lv_timer_t *timer) { - lv_obj_t *chart = timer->user_data; + lv_obj_t *chart = lv_timer_get_user_data(timer); lv_chart_set_next_value2(chart, lv_chart_get_series_next(chart, NULL), lv_rand(0, 200), lv_rand(0, 1000)); } -void example_lvgl_demo_ui(lv_disp_t *disp) +void example_lvgl_demo_ui(lv_display_t *disp) { - lv_obj_t *scr = lv_disp_get_scr_act(disp); + lv_obj_t *scr = lv_display_get_screen_active(disp); lv_obj_t *chart = lv_chart_create(scr); - lv_obj_set_size(chart, 200, 150); + lv_obj_set_size(chart, 400, 300); lv_obj_align(chart, LV_ALIGN_CENTER, 0, 0); - lv_obj_add_event_cb(chart, draw_event_cb, LV_EVENT_DRAW_PART_BEGIN, NULL); - lv_obj_set_style_line_width(chart, 0, LV_PART_ITEMS); /*Remove the lines*/ + lv_obj_add_event_cb(chart, draw_event_cb, LV_EVENT_DRAW_TASK_ADDED, NULL); + lv_obj_add_flag(chart, LV_OBJ_FLAG_SEND_DRAW_TASK_EVENTS); + lv_obj_set_style_line_width(chart, 0, LV_PART_ITEMS); lv_chart_set_type(chart, LV_CHART_TYPE_SCATTER); - lv_chart_set_axis_tick(chart, LV_CHART_AXIS_PRIMARY_X, 5, 5, 5, 1, true, 30); - lv_chart_set_axis_tick(chart, LV_CHART_AXIS_PRIMARY_Y, 10, 5, 6, 5, true, 50); - lv_chart_set_range(chart, LV_CHART_AXIS_PRIMARY_X, 0, 200); lv_chart_set_range(chart, LV_CHART_AXIS_PRIMARY_Y, 0, 1000); diff --git a/examples/peripherals/lcd/rgb_panel/main/rgb_lcd_example_main.c b/examples/peripherals/lcd/rgb_panel/main/rgb_lcd_example_main.c index f388294a41..8b423763a9 100644 --- a/examples/peripherals/lcd/rgb_panel/main/rgb_lcd_example_main.c +++ b/examples/peripherals/lcd/rgb_panel/main/rgb_lcd_example_main.c @@ -1,10 +1,12 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 */ #include +#include +#include #include "sdkconfig.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" @@ -22,7 +24,17 @@ static const char *TAG = "example"; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////// Please update the following configuration according to your LCD spec ////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// FPS = 18000000/(1+40+20+800)/(1+8+4+480) = 42Hz #define EXAMPLE_LCD_PIXEL_CLOCK_HZ (18 * 1000 * 1000) +#define EXAMPLE_LCD_H_RES 800 +#define EXAMPLE_LCD_V_RES 480 +#define EXAMPLE_LCD_HSYNC 1 +#define EXAMPLE_LCD_HBP 40 +#define EXAMPLE_LCD_HFP 20 +#define EXAMPLE_LCD_VSYNC 1 +#define EXAMPLE_LCD_VBP 8 +#define EXAMPLE_LCD_VFP 4 + #define EXAMPLE_LCD_BK_LIGHT_ON_LEVEL 1 #define EXAMPLE_LCD_BK_LIGHT_OFF_LEVEL !EXAMPLE_LCD_BK_LIGHT_ON_LEVEL #define EXAMPLE_PIN_NUM_BK_LIGHT 4 @@ -58,13 +70,17 @@ static const char *TAG = "example"; #define EXAMPLE_LCD_NUM_FB 1 #endif // CONFIG_EXAMPLE_DOUBLE_FB +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// Please update the following configuration according to your Application /////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#define EXAMPLE_LVGL_DRAW_BUF_LINES 50 // number of display lines in each draw buffer #define EXAMPLE_LVGL_TICK_PERIOD_MS 2 -#define EXAMPLE_LVGL_TASK_MAX_DELAY_MS 500 -#define EXAMPLE_LVGL_TASK_MIN_DELAY_MS 1 #define EXAMPLE_LVGL_TASK_STACK_SIZE (4 * 1024) #define EXAMPLE_LVGL_TASK_PRIORITY 2 -static SemaphoreHandle_t lvgl_mux = NULL; +// LVGL library is not thread-safe, this example will call LVGL APIs from different tasks, so use a mutex to protect it +static _lock_t lvgl_api_lock; // we use two semaphores to sync the VSYNC event and the LVGL task, to avoid potential tearing effect #if CONFIG_EXAMPLE_AVOID_TEAR_EFFECT_WITH_SEM @@ -72,7 +88,7 @@ SemaphoreHandle_t sem_vsync_end; SemaphoreHandle_t sem_gui_ready; #endif -extern void example_lvgl_demo_ui(lv_disp_t *disp); +extern void example_lvgl_demo_ui(lv_display_t *disp); static bool example_on_vsync_event(esp_lcd_panel_handle_t panel, const esp_lcd_rgb_panel_event_data_t *event_data, void *user_data) { @@ -85,9 +101,9 @@ static bool example_on_vsync_event(esp_lcd_panel_handle_t panel, const esp_lcd_r return high_task_awoken == pdTRUE; } -static void example_lvgl_flush_cb(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map) +static void example_lvgl_flush_cb(lv_display_t *disp, const lv_area_t *area, uint8_t *px_map) { - esp_lcd_panel_handle_t panel_handle = (esp_lcd_panel_handle_t) drv->user_data; + esp_lcd_panel_handle_t panel_handle = lv_display_get_user_data(disp); int offsetx1 = area->x1; int offsetx2 = area->x2; int offsety1 = area->y1; @@ -97,8 +113,8 @@ static void example_lvgl_flush_cb(lv_disp_drv_t *drv, const lv_area_t *area, lv_ xSemaphoreTake(sem_vsync_end, portMAX_DELAY); #endif // pass the draw buffer to the driver - esp_lcd_panel_draw_bitmap(panel_handle, offsetx1, offsety1, offsetx2 + 1, offsety2 + 1, color_map); - lv_disp_flush_ready(drv); + esp_lcd_panel_draw_bitmap(panel_handle, offsetx1, offsety1, offsetx2 + 1, offsety2 + 1, px_map); + lv_display_flush_ready(disp); } static void example_increase_lvgl_tick(void *arg) @@ -107,44 +123,38 @@ static void example_increase_lvgl_tick(void *arg) lv_tick_inc(EXAMPLE_LVGL_TICK_PERIOD_MS); } -bool example_lvgl_lock(int timeout_ms) -{ - // Convert timeout in milliseconds to FreeRTOS ticks - // If `timeout_ms` is set to -1, the program will block until the condition is met - const TickType_t timeout_ticks = (timeout_ms == -1) ? portMAX_DELAY : pdMS_TO_TICKS(timeout_ms); - return xSemaphoreTakeRecursive(lvgl_mux, timeout_ticks) == pdTRUE; -} - -void example_lvgl_unlock(void) -{ - xSemaphoreGiveRecursive(lvgl_mux); -} - static void example_lvgl_port_task(void *arg) { ESP_LOGI(TAG, "Starting LVGL task"); - uint32_t task_delay_ms = EXAMPLE_LVGL_TASK_MAX_DELAY_MS; + uint32_t time_till_next_ms = 0; while (1) { - // Lock the mutex due to the LVGL APIs are not thread-safe - if (example_lvgl_lock(-1)) { - task_delay_ms = lv_timer_handler(); - // Release the mutex - example_lvgl_unlock(); - } - if (task_delay_ms > EXAMPLE_LVGL_TASK_MAX_DELAY_MS) { - task_delay_ms = EXAMPLE_LVGL_TASK_MAX_DELAY_MS; - } else if (task_delay_ms < EXAMPLE_LVGL_TASK_MIN_DELAY_MS) { - task_delay_ms = EXAMPLE_LVGL_TASK_MIN_DELAY_MS; - } - vTaskDelay(pdMS_TO_TICKS(task_delay_ms)); + _lock_acquire(&lvgl_api_lock); + time_till_next_ms = lv_timer_handler(); + _lock_release(&lvgl_api_lock); + usleep(1000 * time_till_next_ms); } } +static void example_bsp_init_lcd_backlight(void) +{ +#if EXAMPLE_PIN_NUM_BK_LIGHT >= 0 + gpio_config_t bk_gpio_config = { + .mode = GPIO_MODE_OUTPUT, + .pin_bit_mask = 1ULL << EXAMPLE_PIN_NUM_BK_LIGHT + }; + ESP_ERROR_CHECK(gpio_config(&bk_gpio_config)); +#endif +} + +static void example_bsp_set_lcd_backlight(uint32_t level) +{ +#if EXAMPLE_PIN_NUM_BK_LIGHT >= 0 + gpio_set_level(EXAMPLE_PIN_NUM_BK_LIGHT, level); +#endif +} + void app_main(void) { - static lv_disp_draw_buf_t disp_buf; // contains internal graphic buffer(s) called draw buffer(s) - static lv_disp_drv_t disp_drv; // contains callback functions - #if CONFIG_EXAMPLE_AVOID_TEAR_EFFECT_WITH_SEM ESP_LOGI(TAG, "Create semaphores"); sem_vsync_end = xSemaphoreCreateBinary(); @@ -153,14 +163,9 @@ void app_main(void) assert(sem_gui_ready); #endif -#if EXAMPLE_PIN_NUM_BK_LIGHT >= 0 ESP_LOGI(TAG, "Turn off LCD backlight"); - gpio_config_t bk_gpio_config = { - .mode = GPIO_MODE_OUTPUT, - .pin_bit_mask = 1ULL << EXAMPLE_PIN_NUM_BK_LIGHT - }; - ESP_ERROR_CHECK(gpio_config(&bk_gpio_config)); -#endif + example_bsp_init_lcd_backlight(); + example_bsp_set_lcd_backlight(EXAMPLE_LCD_BK_LIGHT_OFF_LEVEL); ESP_LOGI(TAG, "Install RGB LCD panel driver"); esp_lcd_panel_handle_t panel_handle = NULL; @@ -169,7 +174,7 @@ void app_main(void) .dma_burst_size = 64, .num_fbs = EXAMPLE_LCD_NUM_FB, #if CONFIG_EXAMPLE_USE_BOUNCE_BUFFER - .bounce_buffer_size_px = 10 * EXAMPLE_LCD_H_RES, + .bounce_buffer_size_px = 20 * EXAMPLE_LCD_H_RES, #endif .clk_src = LCD_CLK_SRC_DEFAULT, .disp_gpio_num = EXAMPLE_PIN_NUM_DISP_EN, @@ -199,62 +204,61 @@ void app_main(void) .pclk_hz = EXAMPLE_LCD_PIXEL_CLOCK_HZ, .h_res = EXAMPLE_LCD_H_RES, .v_res = EXAMPLE_LCD_V_RES, - // The following parameters should refer to LCD spec - .hsync_back_porch = 40, - .hsync_front_porch = 20, - .hsync_pulse_width = 1, - .vsync_back_porch = 8, - .vsync_front_porch = 4, - .vsync_pulse_width = 1, - .flags.pclk_active_neg = true, + .hsync_back_porch = EXAMPLE_LCD_HBP, + .hsync_front_porch = EXAMPLE_LCD_HFP, + .hsync_pulse_width = EXAMPLE_LCD_HSYNC, + .vsync_back_porch = EXAMPLE_LCD_VBP, + .vsync_front_porch = EXAMPLE_LCD_VFP, + .vsync_pulse_width = EXAMPLE_LCD_VSYNC, + .flags = { + .pclk_active_neg = true, + }, }, .flags.fb_in_psram = true, // allocate frame buffer in PSRAM }; ESP_ERROR_CHECK(esp_lcd_new_rgb_panel(&panel_config, &panel_handle)); - ESP_LOGI(TAG, "Register event callbacks"); - esp_lcd_rgb_panel_event_callbacks_t cbs = { - .on_vsync = example_on_vsync_event, - }; - ESP_ERROR_CHECK(esp_lcd_rgb_panel_register_event_callbacks(panel_handle, &cbs, &disp_drv)); - ESP_LOGI(TAG, "Initialize RGB LCD panel"); ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle)); ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle)); -#if EXAMPLE_PIN_NUM_BK_LIGHT >= 0 ESP_LOGI(TAG, "Turn on LCD backlight"); - gpio_set_level(EXAMPLE_PIN_NUM_BK_LIGHT, EXAMPLE_LCD_BK_LIGHT_ON_LEVEL); -#endif + example_bsp_set_lcd_backlight(EXAMPLE_LCD_BK_LIGHT_ON_LEVEL); ESP_LOGI(TAG, "Initialize LVGL library"); lv_init(); + // create a lvgl display + lv_display_t *display = lv_display_create(EXAMPLE_LCD_H_RES, EXAMPLE_LCD_V_RES); + // associate the rgb panel handle to the display + lv_display_set_user_data(display, panel_handle); + // set color depth + lv_display_set_color_format(display, LV_COLOR_FORMAT_RGB565); + // create draw buffers void *buf1 = NULL; void *buf2 = NULL; #if CONFIG_EXAMPLE_DOUBLE_FB ESP_LOGI(TAG, "Use frame buffers as LVGL draw buffers"); ESP_ERROR_CHECK(esp_lcd_rgb_panel_get_frame_buffer(panel_handle, 2, &buf1, &buf2)); - // initialize LVGL draw buffers - lv_disp_draw_buf_init(&disp_buf, buf1, buf2, EXAMPLE_LCD_H_RES * EXAMPLE_LCD_V_RES); + // set LVGL draw buffers and direct mode + lv_display_set_buffers(display, buf1, buf2, EXAMPLE_LCD_H_RES * EXAMPLE_LCD_V_RES * sizeof(lv_color16_t), LV_DISPLAY_RENDER_MODE_DIRECT); #else - ESP_LOGI(TAG, "Allocate separate LVGL draw buffers from PSRAM"); - buf1 = heap_caps_malloc(EXAMPLE_LCD_H_RES * 100 * sizeof(lv_color_t), MALLOC_CAP_SPIRAM); + ESP_LOGI(TAG, "Allocate LVGL draw buffers"); + // it's recommended to allocate the draw buffer from internal memory, for better performance + size_t draw_buffer_sz = EXAMPLE_LCD_H_RES * EXAMPLE_LVGL_DRAW_BUF_LINES * sizeof(lv_color16_t); + buf1 = heap_caps_malloc(draw_buffer_sz, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); assert(buf1); - // initialize LVGL draw buffers - lv_disp_draw_buf_init(&disp_buf, buf1, buf2, EXAMPLE_LCD_H_RES * 100); + // set LVGL draw buffers and partial mode + lv_display_set_buffers(display, buf1, buf2, draw_buffer_sz, LV_DISPLAY_RENDER_MODE_PARTIAL); #endif // CONFIG_EXAMPLE_DOUBLE_FB - ESP_LOGI(TAG, "Register display driver to LVGL"); - lv_disp_drv_init(&disp_drv); - disp_drv.hor_res = EXAMPLE_LCD_H_RES; - disp_drv.ver_res = EXAMPLE_LCD_V_RES; - disp_drv.flush_cb = example_lvgl_flush_cb; - disp_drv.draw_buf = &disp_buf; - disp_drv.user_data = panel_handle; -#if CONFIG_EXAMPLE_DOUBLE_FB - disp_drv.full_refresh = true; // the full_refresh mode can maintain the synchronization between the two frame buffers -#endif - lv_disp_t *disp = lv_disp_drv_register(&disp_drv); + // set the callback which can copy the rendered image to an area of the display + lv_display_set_flush_cb(display, example_lvgl_flush_cb); + + ESP_LOGI(TAG, "Register event callbacks"); + esp_lcd_rgb_panel_event_callbacks_t cbs = { + .on_vsync = example_on_vsync_event, + }; + ESP_ERROR_CHECK(esp_lcd_rgb_panel_register_event_callbacks(panel_handle, &cbs, display)); ESP_LOGI(TAG, "Install LVGL tick timer"); // Tick interface for LVGL (using esp_timer to generate 2ms periodic event) @@ -266,16 +270,12 @@ void app_main(void) ESP_ERROR_CHECK(esp_timer_create(&lvgl_tick_timer_args, &lvgl_tick_timer)); ESP_ERROR_CHECK(esp_timer_start_periodic(lvgl_tick_timer, EXAMPLE_LVGL_TICK_PERIOD_MS * 1000)); - lvgl_mux = xSemaphoreCreateRecursiveMutex(); - assert(lvgl_mux); ESP_LOGI(TAG, "Create LVGL task"); xTaskCreate(example_lvgl_port_task, "LVGL", EXAMPLE_LVGL_TASK_STACK_SIZE, NULL, EXAMPLE_LVGL_TASK_PRIORITY, NULL); ESP_LOGI(TAG, "Display LVGL Scatter Chart"); // Lock the mutex due to the LVGL APIs are not thread-safe - if (example_lvgl_lock(-1)) { - example_lvgl_demo_ui(disp); - // Release the mutex - example_lvgl_unlock(); - } + _lock_acquire(&lvgl_api_lock); + example_lvgl_demo_ui(display); + _lock_release(&lvgl_api_lock); } diff --git a/examples/peripherals/lcd/rgb_panel/pytest_rgb_panel_lvgl.py b/examples/peripherals/lcd/rgb_panel/pytest_rgb_panel_lvgl.py index 626afd8c75..5c525ec260 100644 --- a/examples/peripherals/lcd/rgb_panel/pytest_rgb_panel_lvgl.py +++ b/examples/peripherals/lcd/rgb_panel/pytest_rgb_panel_lvgl.py @@ -1,6 +1,5 @@ # SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut @@ -19,10 +18,8 @@ from pytest_embedded import Dut def test_rgb_lcd_lvgl(dut: Dut) -> None: dut.expect_exact('example: Turn off LCD backlight') dut.expect_exact('example: Install RGB LCD panel driver') - dut.expect_exact('example: Register event callbacks') dut.expect_exact('example: Initialize RGB LCD panel') dut.expect_exact('example: Turn on LCD backlight') dut.expect_exact('example: Initialize LVGL library') - dut.expect_exact('example: Register display driver to LVGL') dut.expect_exact('example: Install LVGL tick timer') dut.expect_exact('example: Display LVGL Scatter Chart') diff --git a/examples/peripherals/lcd/rgb_panel/sdkconfig.defaults b/examples/peripherals/lcd/rgb_panel/sdkconfig.defaults index d21ca32513..9b31396512 100644 --- a/examples/peripherals/lcd/rgb_panel/sdkconfig.defaults +++ b/examples/peripherals/lcd/rgb_panel/sdkconfig.defaults @@ -1,5 +1,4 @@ -CONFIG_LV_MEM_CUSTOM=y -CONFIG_LV_MEMCPY_MEMSET_STD=y -CONFIG_LV_USE_USER_DATA=y -CONFIG_LV_USE_CHART=y +CONFIG_LV_CONF_SKIP=y +CONFIG_LV_USE_OBSERVER=y +CONFIG_LV_USE_SYSMON=y CONFIG_LV_USE_PERF_MONITOR=y diff --git a/examples/peripherals/lcd/rgb_panel/sdkconfig.defaults.esp32s3 b/examples/peripherals/lcd/rgb_panel/sdkconfig.defaults.esp32s3 index c036baa5a7..4801a05ba0 100644 --- a/examples/peripherals/lcd/rgb_panel/sdkconfig.defaults.esp32s3 +++ b/examples/peripherals/lcd/rgb_panel/sdkconfig.defaults.esp32s3 @@ -4,5 +4,4 @@ CONFIG_SPIRAM_SPEED_80M=y # Enabling the following configurations can help increase the PCLK frequency in the case when # the Frame Buffer is allocated from the PSRAM and fetched by EDMA -CONFIG_SPIRAM_FETCH_INSTRUCTIONS=y -CONFIG_SPIRAM_RODATA=y +CONFIG_SPIRAM_XIP_FROM_PSRAM=y