Hi guys,
I have been struggling for increasing the performance of my IMXRT1062 custom board for several days or weeks. and now I found a solution that I would like to share with you. I got a big improvement in FPS and an important reduction in CPU usage.
I have taken ideas from the these excellent posts from LVGL forum:
https://forum.lvgl.io/t/v8-display-driver-double-buffer-low-fps-high-cpu/6901/24
https://forum.lvgl.io/t/questions-about-define-object-and-effect-on-memory/9778/20
The version of LVGL I'm using is 8.3.5 which is the one that it's included with the SDK 2.14.1. My system is running under FreeRTOS.
My display size is 1024x600 and I'm using 2 frame buffers located in external memory. These buffers are the same size as the display with 16 bit color depth (RGB565).
The changes I did are the following: (in the file lvgl_support.c)
1) In the function lv_port_disp_init:
disp_drv.flush_cb = prv_LCD_flush2; disp_drv.direct_mode = 1; /* Partial refresh */ disp_drv.full_refresh = 0;
2) Create the function prv_LCD_update_dual_buffer:
static void prv_LCD_update_dual_buffer(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *colour_p ) { lv_disp_t* disp = _lv_refr_get_disp_refreshing(); lv_coord_t y, hres = lv_disp_get_hor_res(disp); uint16_t a; lv_color_t *buf_cpy; if( colour_p == disp_drv->draw_buf->buf1) buf_cpy = disp_drv->draw_buf->buf2; else buf_cpy = disp_drv->draw_buf->buf1; for(a = 0; a < disp->inv_p; a++) { if(disp->inv_area_joined[a]) continue; lv_coord_t w = lv_area_get_width(&disp->inv_areas[a]); for(y = disp->inv_areas[a].y1; y <= disp->inv_areas[a].y2 && y < disp_drv->ver_res; y++) { memcpy(buf_cpy+(y * hres + disp->inv_areas[a].x1), colour_p+(y * hres + disp->inv_areas[a].x1), w * sizeof(lv_color_t)); } } }
3) Create the new function flush callback function prv_LCD_flush2
static void prv_LCD_flush2(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p) { DCACHE_CleanInvalidateByRange((uint32_t)color_p, LCD_FB_SIZE); ELCDIF_SetNextBufferAddr(LCDIF, (uint32_t)color_p); s_framePending = true; if(lv_disp_flush_is_last(disp_drv) == true) { prv_LCD_update_dual_buffer(disp_drv, area, color_p); } #if defined(SDK_OS_FREE_RTOS) if (xSemaphoreTake(s_frameSema, portMAX_DELAY) == pdTRUE) { /* IMPORTANT!!! * Inform the graphics library that you are ready with the flushing*/ lv_disp_flush_ready(disp_drv); } else { PRINTF("Display flush failed\r\n"); assert(0); } #else while (s_framePending) { } /* IMPORTANT!!! * Inform the graphics library that you are ready with the flushing*/ lv_disp_flush_ready(disp_drv); #endif }
If you have PXP enabled in lv_conf.h and placed its temporal buffer in a location with enough free space, you should be good to go. In my case I placed the PXP temp buffer in the same external memory as the 2 frame buffers. I'm very happy with the results, from 6FPS to 30+FPS.
Have a nice day and good luck.
Patricio Cohen
Hello patriciocohen,
Thank you for sharing the performance improvement methods to us, I am happy to know you can get better performance. if you have any questions about lvgl and GUI guider. please let us know from following link:
https://community.nxp.com/t5/GUI-Guider/bd-p/GUI-Guider
Best Regards
Zongchun