ESP32 screen corruption at top when running benchmark

As the title says, I’m trying to run some basic benchmarking on a little integrated esp32-s3 with a round screen (480x480).

What I’m facing after a couple of days of troubleshooting is corruption at the top of the screen like some form of corruption or mismatch going on.

Image of what it looks like:

This however goes away once the benchmark is finished and the results are shown so it appears to either be some kind of strange buffer situation or a some kind of flushing before ready condition?

Benchmark finished:

As far as I can tell, I’m doing everything correctly in terms of setup and usage of the underlying esp lcd functionality, but still the problem persists.

Weirdly, if I use the Arduino IDE, and an example I found online here:

I get it to run well (ensuring I choose the options spoken about in the video below) so I picked through the library he’s using (Arduino GFX) so I could copy the esp init details and ensure I’m doing it the same way with the same timings etc, but I still get the same thing.

The details of the screen:
Name of the module: ZX2D10GE01R (Panlee)
480x480 resolution
ST7701S driver
ESP32-S3 N16R8 built in

Software dev environment:
I’m using PlatformIO with ESP-IDF 5.1.1 (as far as I can make out from platformio feedback during upload.

I’m limited by the number of links I can put here as a new user so I’ll upload the code below

I’m attaching here the code for main.c, screen.c, board.h, lv_conf.h, platformio.ini, and sdkconfig.
The platform.ini and sdkconfig files have had .txt added to the end to allow for uploading

Happy to supply more information as needed.

platformioini.txt (854 Bytes)
screen.c (13.3 KB)
main.c (1.1 KB)

board.h (2.1 KB)
lv_conf.h (25.5 KB)
sdkconfigesp32s3box.txt (57.4 KB)

Hi, I got the same issue while running in ESP-IDF V5.1.1
did you solve it ,

Hi @noodlepringle -

Did you find a solution? I have exactly the same issue with the same board, running ESP-IDF v5.1.2.

As an aside - those numbers on the end-screen of the demo are super-high at 19,000 to 20,000? Mine are between 40 and 100.


  1. Downgraded ESP-IDF to earliest 5.x version. Did not help (same issue)
  2. Downgraded ESP-IDF to latest 4.x version. Would not compile

Have also raised an issue in the repo for the hardware.

Ok, after trying LOTS of different things, I have been able to ‘solve’ it by forcing LVGL to redraw the entire framebuffer every time (instead of just the area that has changed). This affects the performance quite a lot so I will continue to investigate to see exactly where the problem occurs. I have a feeling it is not in LVGL but in the code supplied by the manufacturer of the hardware.

To force the redraw of the entire buffer, edit screen.c and find the function called qmsd_rgb_init. Add the following:

disp_drv.full_refresh = 1; // Add this line just after the line above

The problem is in the manufacturers supplied code. I am not sure how it ever would have worked without forcing the entire framebuffer to be rendered.

Every render cycle, a callback is called (lv_disp_drv_t.flush_cb) which passed in the area to draw and a pointer to the pixel data. The manufacturer;s callback looks like this:

static void __qsmd_rgb_disp_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p)
    int offsetx1 = area->x1;
    int offsetx2 = area->x2;
    int offsety1 = area->y1;
    int offsety2 = area->y2;

    esp_lcd_panel_draw_bitmap(g_panel_handle, offsetx1, offsety1, offsetx2 + 1, offsety2 + 1, color_p);

From what I can tell, the pointer to the pixel data (color_p) is always the top of the framebuffer (it alternates between buf0 and buf1) even when a partial area is being drawn. The callback code is using a function called esp_lcd_panel_draw_bitmap (link) to dump a bitmap from the framebuffer to the screen. It expects the pixel data to be contiguous - which it is when drawing the whole framebuffer, but which it never is when drawing a partial area of the buffer :frowning:

I’m not familiar with ESP32 yet, but I’m assuming there will be a function like esp_lcd_panel_draw_bitmap which allows drawing partial bitmaps (specify src and dest offsets and sizes separately). I’ll keep looking.

What you found is really interesting. Do you find any other solution to your problem?

This display is an RGB display The color deoth is 16 bit so it only uses RGB565. There is an SPI attachment as well that is used to set up the bridge driver that is used between the display and the driver IC. You must set the render mode in LVGL to full in order for it to work properly partial mode is not going to work right. You need to use the esp-lcd component soecifically the rgb panel portion of the code. set the driver to use 2 frame buffers in spiram. collect the pointers for the frame buffers from the driver and pass them to the lvgl display driver. This is the important thing, you need to register a vsync callback. in that callback function is when you call the flush ready function in LVGL. This is what will switch the pointers. The rgb driver in the esp-lcd component has DMA memory support for SPIRAM. this allows the double buffering feature in lvgl to work and that is gong to get you the best possible performance. There is a cost of the additional memory use but on the S3 you want to get the model that has 8 mb of SPIRAM which would allow you to do that. YOu can also do it with smaller SPIRAM amounts it all depends on your application code.