Lvgl: How to integrate with FreeRTOS, etc

Created on 3 Aug 2018  路  6Comments  路  Source: lvgl/lvgl

Hi,

I've been working with LVGL (amazing project!) and I am wondering how to integrate it with an RTOS. The README mentions that OS support is available, and I see that you have tested it with FreeRTOS. However, I don't see any locking mechanisms. Is this required or does it "Just Work (TM)?"

question

Most helpful comment

This is how I do it.

static SemaphoreHandle_t uiMutex;

V UI_TakeMutex ( V )
{
    while( xSemaphoreTake( uiMutex, portMAX_DELAY ) != pdTRUE )
        ;
}

V UI_GiveMutex ( V )
{
    xSemaphoreGive( uiMutex );
}

static V TaskLVGL( PV p )
{
    for( ; ; )
    {
        vTaskDelay( pdMS_TO_TICKS(10) );

        UI_TakeMutex();
        lv_task_handler();
        UI_GiveMutex();
    }
}

static V TaskUiEvery200ms ( PV p )
{
    UF8 _400ms, _1000ms;

    for( ; ; )
    {
        vTaskDelay( pdMS_TO_TICKS(200) );

        if( ++_400ms >= 2 )
        {
            _400ms = 0;
            Screens_Every400ms();
        }
        if( ++_1000ms >= 5 )
        {
            _1000ms = 0;
            Screens_Every1000ms();
        }
    }
}

Screens_Every400ms() and Screens_Every1000ms() call UI_TakeMutex and UI_GiveMutex as and if lvgl API functions are called.

All 6 comments

I use lvgl with FreeRTOS. I will do a PR soon on the project esp-open-rtos for the esp8266.
Example link with ssd1306 example: example
i use:
lv_drivers => new_api branch
lvgl => dev-5.2 branch

Hope it is help.

Hi,

Right now there is no locking mechanism but in most cases it is not required to be inside the library.

Once you set up the GUI (create screens, objects etc) usually everything is handled by actions (e.g. button click actions). However, the actions and the related things are called from lv_task_handler (indev_read, disp_flush etc as well). Thus we are worging only from one task so far.

But what if when you need to e.g. update a label with the measured temperature? If you would call lv_label_set_text() from the measuring task it could mess things up because lv_task_handler can come in the middle of lv_label_set_text() or vice-versa. There are two solutions:

  1. Create a "gui_semaphore" and use it around lv_task_handler and in other places where you use LittelvGL "asynchronously".
  2. Create an lv_task to periodically update the required objects or add the GUI updater code below lv_task_handler. This way everything will be in the same task again.

@kisvegabor @Zaltora Thanks for the quick replies!

So all I have to do is ensure that LVGL APIs are only called by one task at a time? That makes it very simple to implement!

This is how I do it.

static SemaphoreHandle_t uiMutex;

V UI_TakeMutex ( V )
{
    while( xSemaphoreTake( uiMutex, portMAX_DELAY ) != pdTRUE )
        ;
}

V UI_GiveMutex ( V )
{
    xSemaphoreGive( uiMutex );
}

static V TaskLVGL( PV p )
{
    for( ; ; )
    {
        vTaskDelay( pdMS_TO_TICKS(10) );

        UI_TakeMutex();
        lv_task_handler();
        UI_GiveMutex();
    }
}

static V TaskUiEvery200ms ( PV p )
{
    UF8 _400ms, _1000ms;

    for( ; ; )
    {
        vTaskDelay( pdMS_TO_TICKS(200) );

        if( ++_400ms >= 2 )
        {
            _400ms = 0;
            Screens_Every400ms();
        }
        if( ++_1000ms >= 5 )
        {
            _1000ms = 0;
            Screens_Every1000ms();
        }
    }
}

Screens_Every400ms() and Screens_Every1000ms() call UI_TakeMutex and UI_GiveMutex as and if lvgl API functions are called.

@markyi370 It seems your question is answered so I close this issue.
If you have further question, feel free to reopen it!

@kisvegabor Yes, my question is answered. Thank you for the quick responses everyone!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

relliktei picture relliktei  路  4Comments

banshanju picture banshanju  路  3Comments

mianhuacar picture mianhuacar  路  5Comments

IronCaterpillar picture IronCaterpillar  路  4Comments

larenge2 picture larenge2  路  4Comments