lvgl icon indicating copy to clipboard operation
lvgl copied to clipboard

[Error] (19234.671, +0) _lv_inv_area: detected modifying dirty areas in render (in lv_refr.c line #212)

Open anghd opened this issue 3 years ago • 2 comments

00

anghd avatar Sep 06 '22 11:09 anghd

What's the problem here?

kisvegabor avatar Sep 08 '22 20:09 kisvegabor

We need some feedback on this issue.

Now we mark this as "stale" because there was no activity here for 14 days.

Remove the "stale" label or comment else this will be closed in 7 days.

lvgl-bot avatar Sep 23 '22 02:09 lvgl-bot

As there was no activity here for a while we close this issue. But don't worry, the conversation is still here and you can get back to it at any time.

So feel free to comment if you have remarks or ideas on this topic.

lvgl-bot avatar Sep 30 '22 02:09 lvgl-bot

What does this error mean. I get them all time also.

codegrue avatar Dec 15 '23 01:12 codegrue

What does this error mean. I get them all time also.

It normally means widget's properties have been modified during rendering(such as DRAW_MAIN event callback). It will cause rendering issues thus are forbidden.

XuNeo avatar Dec 15 '23 01:12 XuNeo

Using FreeRTOS where the UI is being altered in a different thread than the LVGL refresh loop, what is the proper pattern to prevent this kind of conflict?

codegrue avatar Dec 16 '23 01:12 codegrue

LVGL is not thread safe. You can only call LVGL APIs from one thread.

XuNeo avatar Dec 16 '23 02:12 XuNeo

@XuNeo I'm thinking about something like this:

lv_lock();  /*LVGL is not thread safe, so lock it before using any `lv_...` functions in any threads. */
lv_timer_handler(); /*/*Process timers, events, animations, display refreshed, and input devices*/
lv_unlock(); 

lv_lock and lv_unlock are using an lv_mutex internally if LV_USE_OS is set. Without OS they set/clear a bool variable for which we can ASSERT on some critical places. In case of LV_OS_CUSTOM the user can implement these functions.

This practice can be shown all the places so people will intuitively know that is locking is required.

What do you think?

kisvegabor avatar Dec 16 '23 17:12 kisvegabor

Take for example a screen that shows data from an api call. The main loop is calling lv_timer_handler() and another thread calls the API and then updates screen labels when the data cones back. It seems like it's not possible to have this on the same thread without blocking the UI during the API wait period.

codegrue avatar Dec 16 '23 19:12 codegrue

Adding a global lock to lvgl will work. I'm not sure if it's a best practice. Operation to lvgl normally should be done in signal thread and never block it. Move block operations outside of lvgl's thread like using libuv etc.

XuNeo avatar Dec 17 '23 15:12 XuNeo

Once people have an OS, they will use it for sure and will attempt to adjust the widgets from an other thread as well.

kisvegabor avatar Dec 18 '23 12:12 kisvegabor

@kisvegabor I don't see a lv_lock() function available anywhere in the LVGL code... I am using the Arduino framework / FreeRTOS.

codegrue avatar Dec 19 '23 20:12 codegrue

lv_lock is not added yet, we are just talking about it.

If you are calling LVGL function from multiple threads take look at this.

kisvegabor avatar Dec 20 '23 08:12 kisvegabor

Thank you. Wanted to share for FreeRTOS the code looks like this:

SemaphoreHandle_t xLVGLMutexHandle;
TaskHandle_t tUIHandle;
TaskHandle_t tLVGLHandle;

xLVGLMutexHandle = xSemaphoreCreateMutex();
xTaskCreate(uiCallback, "tUIHandle", 3000, (void *)0, tskIDLE_PRIORITY, &tUIHandle);
xTaskCreate(lvglCallback, "tLVGLHandle", 3000, (void *)0, tskIDLE_PRIORITY + 1, &tLVGLHandle);

void lvglCallback(void *p)
{
    while (1)
    {
        // use mutex to insure nothing writes to LVGL during the render
        if (xSemaphoreTake(xLVGLMutexHandle, (TickType_t)10) == pdTRUE)
        {
            lv_timer_handler();

            xSemaphoreGive(xLVGLMutexHandle);
        }

        vTaskDelay(5 / portTICK_PERIOD_MS);
    }
}

void uiCallback(void *p)
{
    while (1)
    {
        // use mutex to lock LVGL before updating UI
        if (xSemaphoreTake(xLVGLMutexHandle, (TickType_t)10) == pdTRUE)
        {
            /* update LVGL UI here */

            xSemaphoreGive(xLVGLMutexHandle);
        }

        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

codegrue avatar Dec 21 '23 22:12 codegrue