Littlevgl RTOS in various tasks

Hi,

Description

There are some examples in esp32(preferably) for use with RTOS in various tasks ?

https://docs.littlevgl.com/en/html/porting/os.html

For example: if i have several tasks that use the littlevgl lib.

What MCU/Processor/Board and compiler are you using?

ESP32. ESP-IDF.

What do you want to achieve?

Several tasks using the littlevgl lib.

What have you tried so far?

Get started examples.

Thank’s.

https://github.com/littlevgl/lv_port_esp32 uses FreeRTOS.

I use this example, but i do not think that this example is purely task-oriented.

I dont think that Purely task-oriented full project use a while(1) infinite loop, Am i wrong ?

while (1) 
{
    vTaskDelay(1);
    lv_task_handler();
}

It would still use a while(1) loop, because one of the threads has to call lv_task_handler repeatedly.

Hi,

I am trying to create a task to call “lv_task_handler( )” periodically, but the esp32(FreeRtos crash).

I tryed with dinamically allocated task and with statically allocated task, but neither worked.

When i comment “lv_task_handler( )” inside task “static void littleVgl_task_handler( void* pvParameters )” and uncomment “printf (“test\n”)” the system works.

Something inside “lv_task_handler( )” is causing the system to crash i think, but it’s strange because if i put “lv_task_handler( )” inside the while loop it works correctly.

// works.
while(1)
{
    lv_task_handler( );
    vTaskDelay(1);
}

Create dinamically allocated task:

// don't works.
/* 
BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pxTaskCode,
							        const char * const pcName,
							        const uint32_t usStackDepth,
							        void * const pvParameters,
							        UBaseType_t uxPriority,
						        	TaskHandle_t * const pxCreatedTask,
                                    const BaseType_t xCoreID 
                                   );	                           
*/ 
xTaskCreatePinnedToCore( littleVgl_task_handler, 
                         "littleVgl_handl", 
                         2048,
                         NULL,
                         1,
                         NULL,    
                         0                         
                       );

vTaskStartScheduler( );

Create statically allocated task:

static StackType_t littleVgl_task_handler_stack_buffer[4096];

static StaticTask_t littleVgl_task_handler_task_data_structure;

/*
TaskHandle_t xTaskCreateStaticPinnedToCore(	TaskFunction_t pxTaskCode,
									        const char * const pcName,
									        const uint32_t ulStackDepth,
									        void * const pvParameters,
									        UBaseType_t uxPriority,
									        StackType_t * const puxStackBuffer,
									        StaticTask_t * const pxTaskBuffer,
                                            const BaseType_t xCoreID 
                                          );
*/

xTaskCreateStaticPinnedToCore( littleVgl_task_handler, 
                               "littleVgl_handl",
                               sizeof(littleVgl_task_handler_stack_buffer),
                               NULL,
                               1,
                               littleVgl_task_handler_stack_buffer,
                               &littleVgl_task_handler_task_data_structure,                            
                               0
                             );

vTaskStartScheduler( );

Task to execute “lv_task_handler( )” every 5 ms.

static void littleVgl_task_handler( void* pvParameters )
{
    TickType_t xLastWakeTime;
    const TickType_t xFrequency = 5;

    // Initialise the xLastWakeTime variable with the current time.
    xLastWakeTime = xTaskGetTickCount ( );
        
    for( ;; )
    { 
        // Wait for the next cycle.
        vTaskDelayUntil( &xLastWakeTime, xFrequency );

        // Perform action here.
        

        //printf("test\n");                

        lv_task_handler( );
    }
}

Thank’s for any help.

For xTaskCreateStaticPinnedToCore, uint32_t ulStackDepth,.
When passing the Stack depth it should be sizeof(littleVgl_task_handler_stack_buffer)/sizeof(StackType_t)

StackType_t = uint8_t.

sizeof(StackType_t) = sizeof(uint8_t) = 1.

Is lv_task_handler the only API you call? Typically you need a mutex to make sure that no other LittlevGL API is concurrently accessing the same data structures.

“Is lv_task_handler the only API you call?”
Yes.

“Typically you need a mutex to make sure that no other LittlevGL API is concurrently accessing the same data structures.”
Only the task that i created call the ‘lv_task_handler’.
Inside ‘lv_task_handler’ it seems to me that it has a mutex. I am using littlevgl 6.0 version.

The already_running variable is not a mutex.; it’s just a reentrancy check for that function.

My only other suggestion would be to try pinning the task to one core but you are doing that already.

1 Like

Hi,

I only removed the “vTaskStartScheduler( )” and it worked.

https://esp32.com/viewtopic.php?t=1336

“Also don’t call vTaskStartScheduler(), this function is called before app_main starts. In fact, app_main runs within a FreeRTOS task already.”

Dont need the while(1) loop at the end of function “void my_app_init( )” too.

The only problem is know the size of stack size needed by task.
With 1024 bytes per example, still crashed with task stack overflow.

void my_app_init( )
{
    .....
    .....
    .....

    TaskHandle_t my_handler;

    xTaskCreatePinnedToCore( littleVgl_task_handler, 
                             "littleVgl_handler", 
                             2048,  // 4096
                             NULL,
                             1,
                             &my_handler,    
                             0                         
                           );
    
    
    configASSERT( my_handler );
}

To check things like this I usually run the application under debugger control and look at the stack buffer to see how much has been used.

Would you like to clarify how can we get the stack buffer usage from FreeRTOS? or you mean by debugging the MCU it self? Where should we look?

If FreeRTOS has a function for checking stack usage, use that and disregard what I’ve mentioned below as their function is probably more accurate.


The method I’ve used in the past is a bit primitive but it doesn’t depend on any complex debugging infrastructure.

If you fill the stack with a known value (e.g. 0xabcdabcd) before your application starts running, you can check how much of it has been overwritten after the application has run, starting from the lowest point of the stack (assuming a descending architecture). This tells you the maximum amount of stack that was used at some point during execution (which is the metric you care about anyways, not just the stack usage at one point in time).

If nearly all of it has been overwritten, your stack size is potentially too small or just barely big enough. It needs to be increased slightly.

If there are still a reasonable amount of 0xabcd entries left, the stack size is probably fine.

I believe the technique is known as “stack coloration” if you want to find more information.

1 Like