LCD RGB888 display bug with PCLK 27MHz

nsaintmartin
Posts: 4
Joined: Mon Jun 17, 2024 9:33 am

LCD RGB888 display bug with PCLK 27MHz

Postby nsaintmartin » Mon Jun 17, 2024 1:42 pm

Setup:
  • board: ESP32-S3-WROOM-1
  • ESP-IDF version: 5.3
  • LVGL version: 9.1
  • LCD Screen: ST7282 display controlled by RGB888
Context:
Test display of an image (in 3 copies) stored in the ESP32 flash (SPIFFS file system).

Here is the code for my 'Screen_Init' function to show you configurations:
  1. esp_err_t Screen_Init(void)
  2. {
  3.     static lv_display_t *display = NULL;
  4.  
  5.     ESP_LOGI(TAG, "Install RGB LCD panel driver");
  6.     esp_lcd_panel_handle_t panel_handle = NULL;
  7.     esp_lcd_rgb_panel_config_t panel_config = {
  8.         .data_width = 8, // RGB888 in parallel mode, thus 8bit in width
  9.         .bits_per_pixel = 24,
  10.         .psram_trans_align = 64,
  11.         .num_fbs = 2,
  12.         .clk_src = LCD_CLK_SRC_DEFAULT,
  13.         .disp_gpio_num = LCD_PIN_NUM_DISP_EN,
  14.         .pclk_gpio_num = LCD_PIN_NUM_PCLK,
  15.         .vsync_gpio_num = LCD_PIN_NUM_VSYNC,
  16.         .hsync_gpio_num = LCD_PIN_NUM_HSYNC,
  17.         .de_gpio_num = LCD_PIN_NUM_DE,
  18.         .data_gpio_nums = {
  19.             LCD_PIN_NUM_DATA0,
  20.             LCD_PIN_NUM_DATA1,
  21.             LCD_PIN_NUM_DATA2,
  22.             LCD_PIN_NUM_DATA3,
  23.             LCD_PIN_NUM_DATA4,
  24.             LCD_PIN_NUM_DATA5,
  25.             LCD_PIN_NUM_DATA6,
  26.             LCD_PIN_NUM_DATA7,
  27.         },
  28.         .timings = {
  29.             .pclk_hz = 27000000,
  30.             .h_res = 480,
  31.             .v_res = 272,
  32.             // The following parameters should refer to LCD spec
  33.             .hsync_back_porch = 43,
  34.             .hsync_front_porch = 8,
  35.             .hsync_pulse_width = 4,
  36.             .vsync_back_porch = 12,
  37.             .vsync_front_porch = 8,
  38.             .vsync_pulse_width = 4,
  39.             .flags.pclk_active_neg = true,
  40.         },
  41.         .flags = {
  42.             .fb_in_psram = true, // allocate frame buffer in PSRAM
  43.             .disp_active_low = 0,
  44.         }
  45.     };
  46.  
  47.     ESP_ERROR_CHECK(esp_lcd_new_rgb_panel(&panel_config, &panel_handle));
  48.  
  49.     ESP_LOGI(TAG, "Register event callbacks");
  50.     esp_lcd_rgb_panel_event_callbacks_t cbs = {
  51.         .on_vsync = on_vsync_event,
  52.     };
  53.    
  54.     ESP_ERROR_CHECK(esp_lcd_rgb_panel_register_event_callbacks(panel_handle, &cbs, display));
  55.  
  56.     ESP_LOGI(TAG, "Initialize RGB LCD panel");
  57.     ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle));
  58.     ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle));
  59.  
  60.     esp_lcd_panel_disp_on_off(panel_handle, true);
  61.  
  62.     ESP_LOGI(TAG, "Initialize LVGL library");
  63.     lv_init();
  64.  
  65.     void *buf1 = NULL;
  66.     void *buf2 = NULL;
  67.  
  68.     ESP_LOGI(TAG, "Use frame buffers as LVGL draw buffers");
  69.     ESP_ERROR_CHECK(esp_lcd_rgb_panel_get_frame_buffer(panel_handle, 2, &buf1, &buf2));
  70.  
  71.     display = lv_display_create(480, 272);
  72.     lv_display_set_flush_cb (display, lvgl_flush_cb);
  73.     lv_display_set_user_data(display, panel_handle);
  74.     // initialize LVGL draw buffers
  75.     lv_display_set_buffers(display, buf1, buf1, 480* 272* sizeof(lv_color_t), LV_DISPLAY_RENDER_MODE_FULL);
  76.  
  77.     ESP_LOGI(TAG, "Install LVGL tick timer");
  78.     // Tick interface for LVGL (using esp_timer to generate 2ms periodic event)
  79.     const esp_timer_create_args_t lvgl_tick_timer_args = {
  80.         .callback = &increase_lvgl_tick,
  81.         .name = "lvgl_tick"
  82.     };
  83.     esp_timer_handle_t lvgl_tick_timer = NULL;
  84.     ESP_ERROR_CHECK(esp_timer_create(&lvgl_tick_timer_args, &lvgl_tick_timer));
  85.     ESP_ERROR_CHECK(esp_timer_start_periodic(lvgl_tick_timer, LCD_LVGL_TICK_PERIOD_MS * 1000));
  86.  
  87.     lv_obj_t *scr = lv_disp_get_scr_act(display);
  88.     /// Set cyan background
  89.     lv_obj_set_style_bg_color(scr, (lv_color_t){0x00, 0xBC, 0xD4}, LV_PART_MAIN);
  90.  
  91.     /// Display an image readed in flash
  92.     screen_display_image();
  93.  
  94.     /// main task creation
  95.     while (1) {
  96.         // raise the task priority of LVGL and/or reduce the handler period can improve the performance
  97.         vTaskDelay(pdMS_TO_TICKS(10));
  98.         // The task running lv_timer_handler should have lower priority than that running `lv_tick_inc`
  99.         lv_timer_handler();
  100.     }
  101.     return ESP_OK;
  102. }
Problem encountered:
When pressing the reset button on the ESP32-S3-WROOM-1 card, the screen display changes randomly (color of images and background varies and display shifts, see photo). The bug only occurs when an image is retrieved from the flash. No problem displaying any element of the LVGL lib (lines, shapes...).

Tests and debugs carried out:
  • console display of the first 50 bytes of the displayed frame buffer: data corresponds to expectations, so we have the right data in the frame buffer.
  • same image stored in an array rather than in flash: no more bugs
  • lower PCLK speed (e.g. 20MHz instead of 27MHz): no bugs (see photo attached to visualize the expected result)
  • if you retrieve the image in flash before configuring the panel handle and lvgl, configure them and then display the image: no bug
Here a video to visualize the problem:
https://drive.google.com/file/d/1Nq2kTN ... drive_link

Thank you in advance for your help.

PS: Don't hesitate to ask me for more details, I wanted to keep things fairly condensed.
Attachments
PCLK_20MHz.jpg
Display with PCLK at 20MHz (as expected)
PCLK_20MHz.jpg (2.13 MiB) Viewed 1368 times

MicroController
Posts: 1704
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: LCD RGB888 display bug with PCLK 27MHz

Postby MicroController » Tue Jun 18, 2024 7:36 am

May be irrelevant, but is

Code: Select all

lv_display_set_buffers(display, buf1, buf1, 480* 272* sizeof(lv_color_t), LV_DISPLAY_RENDER_MODE_FULL);
using buf1 twice intentional?

And it might be helpful to see the code that actually doesn't do what it should, i.e. screen_display_image().

nsaintmartin
Posts: 4
Joined: Mon Jun 17, 2024 9:33 am

Re: LCD RGB888 display bug with PCLK 27MHz

Postby nsaintmartin » Tue Jun 18, 2024 7:57 am

You're right, it's

Code: Select all

lv_display_set_buffers(display, buf1, buf2, 480* 272* sizeof(lv_color_t), LV_DISPLAY_RENDER_MODE_FULL);
copy and paste error when I wrote my post for the forum.

Yeah sure :

Code: Select all

void screen_display_image(void)
{

    FILE *f;
    f = fopen("/spiffs/ICON_DEVICE_VBC8_PENDENT_COLOR", "r");
    if (!f) 
    {
        ESP_LOGE(TAG, "FAILED TO OPEN IMAGE");
        return;
    }

    uint16_t width = 36, height = 40;   // ICON_DEVICE_VBC8_PENDENT_COLOR

    size_t image_size = width * height * 2;
    uint16_t *image_data = (uint16_t *)malloc(image_size);
    if (!image_data) 
    {
        ESP_LOGE(TAG, "Failed to allocate memory for image data");
        fclose(f);
        return;
    }

    size_t read_size = fread(image_data, sizeof(uint16_t), image_size/2, f);
    fclose(f);
    if (read_size != image_size/2) 
    {
        ESP_LOGE(TAG, "Failed to read image data");
        free(image_data);
        return;
    }

    lv_color_t *lv_image = (lv_color_t*)malloc(width*height*sizeof(lv_color_t));
    if (!lv_image) 
    {
        ESP_LOGE(TAG, "FAILED TO ALLOCATE MEMORY FOR LVGL IMAGE");
        free(image_data);
        return;
    }
    
    /// convert image data from rgb565 to rgb888
    convert_rgb565_to_rgb888(image_data, lv_image, width, height);

    /// Create LVGL image 
    static lv_img_dsc_t img_dsc; 
    img_dsc.header.w = width; 
    img_dsc.header.h = height; 
    img_dsc.data_size = width*height*LV_COLOR_DEPTH/8; 
    img_dsc.header.cf = LV_COLOR_FORMAT_RGB888; 
    img_dsc.header.stride = width*LV_COLOR_DEPTH/8;
    img_dsc.data = (const uint8_t *)lv_image; 

    
    /// Display the image on the LVGL screen 
    lv_obj_t *img1 = lv_image_create(lv_screen_active()); 
    lv_obj_t *img2 = lv_image_create(lv_screen_active()); 
    lv_obj_t *img3 = lv_image_create(lv_screen_active()); 

    lv_image_set_src(img1, &img_dsc); 
    lv_obj_align(img1, LV_ALIGN_TOP_LEFT, 0, 0); 

    lv_image_set_src(img2, &img_dsc); 
    lv_obj_align(img2, LV_ALIGN_CENTER, 0, 0); 

    lv_image_set_src(img3, &img_dsc); 
    lv_obj_align(img3, LV_ALIGN_BOTTOM_RIGHT, 0, 0); 
    
    /// Free allocated memory (LVGL will take care of the image data) 
    free(lv_image); 
    free(image_data);

}
Simple retrieval of an image stored in flash (bitmat in RGB565 format, which I convert to RGB888).

MicroController
Posts: 1704
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: LCD RGB888 display bug with PCLK 27MHz

Postby MicroController » Tue Jun 18, 2024 1:28 pm

Code: Select all

    /// Free allocated memory (LVGL will take care of the image data) 
    free(lv_image); 
I don't know LVGL enough to tell, but I'm not sure if it's ok to free the image at this point already. (When does LVGL do the drawing/rendering into the frame buffer?)

nsaintmartin
Posts: 4
Joined: Mon Jun 17, 2024 9:33 am

Re: LCD RGB888 display bug with PCLK 27MHz

Postby nsaintmartin » Tue Jun 18, 2024 2:58 pm

No it's not a problem, the data is copied into the img1 (or 2 or 3) object with the lv_image_set_src() function.

But I think the problem is much deeper, maybe related to DMA or something like that, I don't know.

Someone should be able to reproduce my bug, do you work for Espressif @MicroController ?

nsaintmartin
Posts: 4
Joined: Mon Jun 17, 2024 9:33 am

Re: LCD RGB888 display bug with PCLK 27MHz

Postby nsaintmartin » Thu Jun 20, 2024 7:36 am

It's not a problem to free lv_image as the data is copied to the img1 (or img2 or img3) object in the lv_image_create() function.

But I think the problem is much deeper than that, maybe a DMA problem or something... The display works well with a clock lower than 22MHz, but as soon as I want to go higher the bug is there, and I want to reach 27MHz as this is the speed recommended in the datasheet for the screen I'm using for an RGB888 display.

Someone should reproduce this bug, do you work for espressif @MicroController?

MicroController
Posts: 1704
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: LCD RGB888 display bug with PCLK 27MHz

Postby MicroController » Fri Jun 21, 2024 9:36 pm

nsaintmartin wrote:
Thu Jun 20, 2024 7:36 am
do you work for espressif @MicroController?
Maybe some day when I grow up... ;)

MicroController
Posts: 1704
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: LCD RGB888 display bug with PCLK 27MHz

Postby MicroController » Fri Jun 21, 2024 10:26 pm

nsaintmartin wrote:
Thu Jun 20, 2024 7:36 am
It's not a problem to free lv_image as the data is copied to the img1 (or img2 or img3) object
Looking at https://github.com/lvgl/lvgl/blob/e4258 ... age.c#L192 I'm not convinced there's any copying going on.

Combined with
same image stored in an array rather than in flash: no more bugs
I'd say we pretty much pinpointed the issue.

Who is online

Users browsing this forum: Bing [Bot] and 79 guests