Race conditions, expensive function calls

Hello LVGL community,

i have successfully made my first experiments with lvgl on the ESP32s3 and a ST7789 based display. Everything works very well so far (after I understood that the reset line has no integrated pull-up…).
Before I do the next steps, I want to clarify two issues:

1.) Analogous to Expressif’s example, I use a timer that calls the function “lv_tick_inc” in a 2ms cycle. Furthermore I call the function lv_timer_handler() in a separate thread.
I want to do the update of the UI elements via the function lv_label_set_text in another thread. Do I have to synchronize the calls of lv_label_set_text or are there no threading problems to worry about?

  1. If I understood it correctly in the source code, the lv_label_set_text function does not check if something has changed in the text to be displayed. Instead, the assigned screen content is ALWAYS invalidated and ALWAYS redrawn. So the call can be described as “expensive”. So if the value changes very rarely, it would be very inefficient to call the function in a 10ms cycle. I should rather check externally if the value has changed and call the lv_label_set_text() function only in the positive case. Is this correct?

Thanks for an answer or for links pointing to available answers!

Regards,

Klaus

lvgl is not thread safe. If you use lvgl functions from diffferent threads, you have to use a mutex/semaphore to gain exclusive access.
It is also a problem if you call a lvgl function from an ISR.

See Tasks and Threads for more details.

a 2 millisecond timer (ISR) is also too fast. set it to maybe a 20 millisecond timer and make the call to lv_tick_inc right before you call lv_task_handler. You will want to keep track of the amount of time that passes between times the timer gets run as the timer is not going to run at exactly 20 milliseconds each time. it will always be at least 20 milliseconds but can be longer.

I wouldn’t even use an ISR for this because of memory allocation. I would keep track of the time that passes and call lv_tick_inc and lv_timer_handler in your main loop.

Hi @Klaus ,

I don’t know if this is still relevant for you but in answer to your question 2, I only update GUI label items (in fact all items including text areas) if they have actually changed, before I came to that conclusion my GUI was very slow. So yes I believe checking externally if the values have changed is essential.

I found a good way to optimise this and visualise what is happening is to enable the following option in lv_conf.h:

/*1: Draw random colored rectangles over the redrawn areas*/
#define LV_USE_REFR_DEBUG 1

(I am sure you know this but be sure to rebuild and relink the library after this change!)

Whilst this completely destroys the performance of the system you can however see exactly what is being refreshed on the screen, I have some very complex large screens and this helped me to optimise them with ease.

I hope that helps.

Kind Regards,

Pete

Thanks to all for these valuable tips and tricks!

Regards, Klaus

1 Like