The simplest and work example of LVGL + freeRTOS

I have been running the project code on my device quite successfully using TFT_eSPI and freeRTOS.
Simple code for this:

#include <Arduino.h> // include freeRTOS also
#include <TFT_eSPI.h> // Library for TFT display

TFT_eSPI tft = TFT_eSPI(); // Create object for the display

const int SCREEN_WIDTH = 360;
const int SCREEN_HEIGHT = 360;

float angle = 0.0; // Global variable for the rotation angle

// Function to draw the line
void drawLine(void *pvParameters) {
    while (true) {
        tft.fillScreen(TFT_BROWN); // Brown background
        
        // Center and length of the line
        int centerX = SCREEN_WIDTH / 2;
        int centerY = SCREEN_HEIGHT / 2;
        int length = 100; 

        // Coordinates of the line's endpoints
        int x1 = centerX + cos(angle) * length / 2;
        int y1 = centerY + sin(angle) * length / 2;
        int x2 = centerX - cos(angle) * length / 2;
        int y2 = centerY - sin(angle) * length / 2;

        tft.drawLine(x1, y1, x2, y2, TFT_WHITE); // Draw the line
        
        vTaskDelay(20 / portTICK_PERIOD_MS); // Delay for frame rate
    }
}

// Function to rotate the line
void rotateLine(void *pvParameters) {
    while (true) {
        angle += 0.05; // Update angle
        if (angle >= 2 * PI) angle -= 2 * PI; // Limit angle
        
        vTaskDelay(20 / portTICK_PERIOD_MS); // Delay for update rate
    }
}

void setup() {
    tft.init();
    tft.setRotation(1); // Set display orientation
    tft.fillScreen(TFT_BROWN); // Brown background
    
    // Create tasks for drawing and rotating
    xTaskCreate(drawLine, "Draw Line", 2048, NULL, 1, NULL);
    // xTaskCreate(rotateLine, "Rotate Line", 2048, NULL, 1, NULL);
    xTaskCreatePinnedToCore(rotateLine, "Rotate Line", 2048, NULL, 1, &rotateTask, 0); // Pin to core 0
}

void loop() {
    // Main loop is empty
}

As you can see from this simple code, you can run two tasks on two cores that is assigned to esp32s3 by default, using the flag

"extra_flags": [
"-DARDUINO_RUNNING_CORE=1",
],

in the board settings file

board = esp32-s3-devkitc-1-n16r8

Now I want to do a similar procedure with the library LVGL 9.3, the code for a simple example in this case is:

#include "Arduino.h"
#include <lvgl.h>
#include <Arduino_GFX_Library.h>

Arduino_DataBus *bus = new Arduino_ESP32QSPI(
    10 /* CS */, 9 /* SCK */, 11 /* D0 - mosi */, 12 /* D1 - miso */, 13 /* D2 - quadwp */, 14 /* D3 - quadhd */);
Arduino_GFX *gfx = new Arduino_ST77916(bus, 47 /* RST */, 0 /* rotation */, true /* IPS */, 360 /* width */, 360 /* height */);

// Global variables for angle and display settings
float angle = 0.0; 
const int SCREEN_WIDTH = 480;
const int SCREEN_HEIGHT = 320;

// Backlight PIN
#define GFX_BL 15

uint32_t screenWidth;
uint32_t screenHeight;
uint32_t drawBufSize;
lv_display_t *disp;

lv_obj_t * canvas;

uint32_t millis_cb(void)
{
  return millis();
}

void my_disp_flush(lv_display_t *disp, const lv_area_t *area, uint8_t *px_map) // LVGL 9.3
{
  uint32_t w = lv_area_get_width(area);
  uint32_t h = lv_area_get_height(area);

  gfx->draw16bitRGBBitmap(area->x1, area->y1, (uint16_t *)px_map, w, h); // LVGL 9.3

  /*Call it to tell LVGL you are ready*/
  lv_disp_flush_ready(disp);
}

#define CANVAS_WIDTH  50
#define CANVAS_HEIGHT  50

// Function to create a rotating line
void drawLine(lv_obj_t *canvas) {
    /*Create a buffer for the canvas*/
    LV_DRAW_BUF_DEFINE_STATIC(draw_buf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_ARGB8888);
    LV_DRAW_BUF_INIT_STATIC(draw_buf);

    /*Create a canvas and initialize its palette*/
    canvas = lv_canvas_create(lv_screen_active());
    lv_canvas_set_draw_buf(canvas, &draw_buf);
    lv_canvas_fill_bg(canvas, lv_color_hex3(0xccc), LV_OPA_COVER);
    lv_obj_center(canvas);

    lv_layer_t layer;
    lv_canvas_init_layer(canvas, &layer);

    lv_draw_line_dsc_t dsc;
    lv_draw_line_dsc_init(&dsc);
    dsc.color = lv_palette_main(LV_PALETTE_RED);
    dsc.width = 4;
    dsc.round_end = 1;
    dsc.round_start = 1;
    dsc.p1.x = 15;
    dsc.p1.y = 15;
    dsc.p2.x = 35;
    dsc.p2.y = 10;
    lv_draw_line(&layer, &dsc);

    lv_canvas_finish_layer(canvas, &layer);
}

// Task to update the rotation angle
void rotateLine(void *pvParameters) {
    // lv_obj_t *canvas = (lv_obj_t *)pvParameters; // Get the canvas object

    while (true) {
        angle += 0.05; // Increment the angle
        if (angle >= 2 * M_PI) angle -= 2 * M_PI; // Wrap around angle

        drawLine(canvas); // Call function to draw the line
        vTaskDelay(20 / portTICK_PERIOD_MS); // Delay for update rate
    }
}

void setup() {

    // Init Display
    if (!gfx->begin())
    {
        Serial.println("gfx->begin() failed!");
    }

    gfx->fillScreen(RGB565_YELLOW);

    #ifdef GFX_BL
        pinMode(GFX_BL, OUTPUT);
        digitalWrite(GFX_BL, HIGH);
    #endif

    lv_init(); // Initialize LVGL

    /*Set a tick source so that LVGL will know how much time elapsed. */
    lv_tick_set_cb(millis_cb);

    screenWidth = gfx->width();
    screenHeight = gfx->height();

    drawBufSize = screenWidth * screenHeight;

    disp = lv_display_create(screenWidth, screenHeight);
    lv_display_set_flush_cb(disp, my_disp_flush);

    static void* buf1 = (lv_color_t*)heap_caps_malloc(drawBufSize, MALLOC_CAP_SPIRAM);
    static void* buf2 = (lv_color_t*)heap_caps_malloc(drawBufSize, MALLOC_CAP_SPIRAM);

    lv_display_set_buffers(disp, buf1, buf2, drawBufSize, LV_DISPLAY_RENDER_MODE_PARTIAL);

    // Create a canvas object for drawing
    // lv_obj_t *canvas = lv_canvas_create(lv_scr_act()); // No work
    lv_obj_t *canvas = lv_canvas_create( lv_screen_active()); // Work
   
    lv_obj_set_size(canvas, SCREEN_WIDTH, SCREEN_HEIGHT); // Set canvas size
    lv_obj_align(canvas, LV_ALIGN_CENTER, 0, 0); // Center the canvas

    // Create task for rotating line
    xTaskCreatePinnedToCore(rotateLine, "Rotate Line", 4096, NULL, 1, NULL, 0); // Pin to core 0
}

void loop() {
    lv_task_handler(); // Handle LVGL tasks
    vTaskDelay(5 / portTICK_PERIOD_MS); // Small delay
}

Platformio.ini here

build_flags = 
  -D LV_CONF_SKIP
  -D LV_CONF_INCLUDE_SIMPLE
  -D LV_USE_SYSMON=1
  -D LV_USE_PERF_MONITOR=1
  -D LV_USE_PERF_MONITOR_POS="LV_ALIGN_BOTTOM_MID"

  -D LV_USE_LOG=1
  -D LV_MEM_SIZE="(128U * 1024U)"
  -D LV_USE_FREERTOS_TASK_NOTIFY=1

  -D LV_DEF_REFR_PERIOD=5

The code compiles and loads into the device fine, but the result is only a yellow screen:

gfx->fillScreen(RGB565_YELLOW);

If I uncomment the line from the Setup section:

lv_obj_t *canvas = lv_canvas_create(lv_screen_active()); // Create canvas

The device will load the image, but there are no rotations and the device will reboot.

ELF file SHA256: 23b901996f8eec9f

Rebooting…
ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0xc (RTC_SW_CPU_RST),boot:0xb (SPI_FAST_FLASH_BOOT)
Saved PC:0x40377834
#0 0x40377834 in esp_restart_noos at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_system/port/soc/esp32s3/system_internal.c:151 (discriminator 1)

SPIWP:0xee
mode:DIO, clock div:1
load:0x3fce3808,len:0x4bc
load:0x403c9700,len:0xbd8
load:0x403cc700,len:0x2a0c
entry 0x403c98d0
E (11933) task_wdt: Task watchdog got triggered. The following tasks did not reset the watchdog in time:
E (11933) task_wdt: - IDLE0 (CPU 0)
E (11933) task_wdt: Tasks currently running:
E (11933) task_wdt: CPU 0: Rotate Line
E (11933) task_wdt: CPU 1: loopTask
E (11933) task_wdt: Aborting.

abort() was called at PC 0x4204463c on core 0
#0 0x4204463c in task_wdt_isr at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_system/task_wdt.c:176 (discriminator 3)

Backtrace: 0x40377bfe:0x3fc94c50 0x4037b339:0x3fc94c70 0x40381a45:0x3fc94c90 0x4204463c:0x3fc94d10 0x40378e41:0x3fc94d30 0x4205d8b8:0x3fced190 0x4201274f:0x3fced1b0 0x4201293e:0x3fced1e0 0x42011aa8:0x3fced200 0x42012b2e:0x3fced220 0x42023e50:0x3fced240 0x42018419:0x3fced270 0x420019a1:0x3fced290 0x42001a81:0x3fced360
#0 0x40377bfe in panic_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_system/panic.c:408
#1 0x3fc94c50 in port_IntStack at ??:?
#2 0x4037b339 in esp_system_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_system/esp_system.c:137
#3 0x3fc94c70 in port_IntStack at ??:?
#4 0x40381a45 in abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/newlib/abort.c:46
#5 0x3fc94c90 in port_IntStack at ??:?
#6 0x4204463c in task_wdt_isr at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_system/task_wdt.c:176 (discriminator 3)
#7 0x3fc94d10 in port_IntStack at ??:?
#8 0x40378e41 in _xt_lowint1 at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port/xtensa/xtensa_vectors.S:1118
#9 0x3fc94d30 in port_IntStack at ??:?
#10 0x4205d8b8 in lv_assert_handler at lib/lvgl/src/misc/lv_assert.c:37
#11 0x4201274f in block_locate_free at lib/lvgl/src/stdlib/builtin/lv_tlsf.c:774
(inlined by) block_locate_free at lib/lvgl/src/stdlib/builtin/lv_tlsf.c:754
#12 0x4201293e in lv_tlsf_malloc at lib/lvgl/src/stdlib/builtin/lv_tlsf.c:1101
#13 0x42011aa8 in lv_malloc_core at lib/lvgl/src/stdlib/builtin/lv_mem_core_builtin.c:144
#14 0x42012b2e in lv_malloc_zeroed at lib/lvgl/src/stdlib/lv_mem.c:100
(inlined by) lv_malloc_zeroed at lib/lvgl/src/stdlib/lv_mem.c:92
#15 0x42023e50 in lv_obj_class_create_obj at lib/lvgl/src/core/lv_obj_class.c:51
#16 0x42018419 in lv_canvas_create at lib/lvgl/src/widgets/canvas/lv_canvas.c:62
#17 0x420019a1 in drawLine(_lv_obj_t*) at src/RTOS_LVGL_9_simple.cpp:59
#18 0x42001a81 in rotateLine(void*) at src/RTOS_LVGL_9_simple.cpp:90

Unfortunately, I didn’t see any examples of lvgl + freeRTOS in the repository

or any working examples on the Internet :roll_eyes: