Frozen screen after some cicles

What do you want to achieve?

I’m trying to create an interface to show Temperature, Humidity and pollution with dedicated sensors.
I have only one screen with:

  • two labels
  • two arcs
  • two panels
  • two bars

this is the code

// This file was generated by SquareLine Studio
// SquareLine Studio version: SquareLine Studio 1.3.2
// LVGL version: 8.3.6
// Project name: Particulate_reader

#include "../ui.h"

void ui_Screen1_screen_init(void)
{
ui_Screen1 = lv_obj_create(NULL);
lv_obj_clear_flag( ui_Screen1, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_ELASTIC | LV_OBJ_FLAG_SCROLL_MOMENTUM );    /// Flags
lv_obj_set_style_border_color(ui_Screen1, lv_color_hex(0xD10D69), LV_PART_MAIN | LV_STATE_DEFAULT );
lv_obj_set_style_border_opa(ui_Screen1, 0, LV_PART_MAIN| LV_STATE_DEFAULT);

ui_TempIndicator = lv_obj_create(ui_Screen1);
lv_obj_set_width( ui_TempIndicator, 244);
lv_obj_set_height( ui_TempIndicator, 28);
lv_obj_set_x( ui_TempIndicator, 0 );
lv_obj_set_y( ui_TempIndicator, -120 );
lv_obj_set_align( ui_TempIndicator, LV_ALIGN_BOTTOM_MID );
lv_obj_clear_flag( ui_TempIndicator, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | LV_OBJ_FLAG_SNAPPABLE | LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_ELASTIC | LV_OBJ_FLAG_SCROLL_MOMENTUM | LV_OBJ_FLAG_SCROLL_CHAIN );    /// Flags
lv_obj_set_style_bg_color(ui_TempIndicator, lv_color_hex(0xD10D69), LV_PART_MAIN | LV_STATE_DEFAULT );
lv_obj_set_style_bg_opa(ui_TempIndicator, 20, LV_PART_MAIN| LV_STATE_DEFAULT);
lv_obj_set_style_border_color(ui_TempIndicator, lv_color_hex(0xD10D69), LV_PART_MAIN | LV_STATE_DEFAULT );
lv_obj_set_style_border_opa(ui_TempIndicator, 0, LV_PART_MAIN| LV_STATE_DEFAULT);

ui_HumIndicator = lv_obj_create(ui_Screen1);
lv_obj_set_width( ui_HumIndicator, 244);
lv_obj_set_height( ui_HumIndicator, 32);
lv_obj_set_x( ui_HumIndicator, 0 );
lv_obj_set_y( ui_HumIndicator, 120 );
lv_obj_set_align( ui_HumIndicator, LV_ALIGN_TOP_MID );
lv_obj_clear_flag( ui_HumIndicator, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | LV_OBJ_FLAG_SNAPPABLE | LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_ELASTIC | LV_OBJ_FLAG_SCROLL_MOMENTUM | LV_OBJ_FLAG_SCROLL_CHAIN );    /// Flags
lv_obj_set_style_bg_color(ui_HumIndicator, lv_color_hex(0x3C91E6), LV_PART_MAIN | LV_STATE_DEFAULT );
lv_obj_set_style_bg_opa(ui_HumIndicator, 20, LV_PART_MAIN| LV_STATE_DEFAULT);
lv_obj_set_style_border_color(ui_HumIndicator, lv_color_hex(0x3C91E6), LV_PART_MAIN | LV_STATE_DEFAULT );
lv_obj_set_style_border_opa(ui_HumIndicator, 0, LV_PART_MAIN| LV_STATE_DEFAULT);

ui_temperature = lv_arc_create(ui_Screen1);
lv_obj_set_width( ui_temperature, 230);
lv_obj_set_height( ui_temperature, 230);
lv_obj_set_align( ui_temperature, LV_ALIGN_CENTER );
lv_obj_clear_flag( ui_temperature, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | LV_OBJ_FLAG_SNAPPABLE | LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_ELASTIC | LV_OBJ_FLAG_SCROLL_MOMENTUM | LV_OBJ_FLAG_SCROLL_CHAIN );    /// Flags
lv_arc_set_value(ui_temperature, 25);
lv_arc_set_bg_angles(ui_temperature,0,100);
lv_arc_set_rotation(ui_temperature,185);

lv_obj_set_style_arc_color(ui_temperature, lv_color_hex(0xD90368), LV_PART_INDICATOR | LV_STATE_DEFAULT );
lv_obj_set_style_arc_opa(ui_temperature, 255, LV_PART_INDICATOR| LV_STATE_DEFAULT);

lv_obj_set_style_bg_color(ui_temperature, lv_color_hex(0xB9065A), LV_PART_KNOB | LV_STATE_DEFAULT );
lv_obj_set_style_bg_opa(ui_temperature, 255, LV_PART_KNOB| LV_STATE_DEFAULT);
lv_obj_set_style_pad_left(ui_temperature, 0, LV_PART_KNOB| LV_STATE_DEFAULT);
lv_obj_set_style_pad_right(ui_temperature, 0, LV_PART_KNOB| LV_STATE_DEFAULT);
lv_obj_set_style_pad_top(ui_temperature, 0, LV_PART_KNOB| LV_STATE_DEFAULT);
lv_obj_set_style_pad_bottom(ui_temperature, 0, LV_PART_KNOB| LV_STATE_DEFAULT);

ui_temptxt = lv_label_create(ui_temperature);
lv_obj_set_width( ui_temptxt, LV_SIZE_CONTENT);  /// 1
lv_obj_set_height( ui_temptxt, LV_SIZE_CONTENT);   /// 1
lv_obj_set_x( ui_temptxt, -25 );
lv_obj_set_y( ui_temptxt, -29 );
lv_obj_set_align( ui_temptxt, LV_ALIGN_CENTER );
lv_label_set_text(ui_temptxt,"25 °C");
lv_obj_clear_flag( ui_temptxt, LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | LV_OBJ_FLAG_SNAPPABLE | LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_ELASTIC | LV_OBJ_FLAG_SCROLL_MOMENTUM | LV_OBJ_FLAG_SCROLL_CHAIN );    /// Flags
lv_obj_set_style_text_color(ui_temptxt, lv_color_hex(0xD10D69), LV_PART_MAIN | LV_STATE_DEFAULT );
lv_obj_set_style_text_opa(ui_temptxt, 255, LV_PART_MAIN| LV_STATE_DEFAULT);
lv_obj_set_style_text_font(ui_temptxt, &lv_font_montserrat_40, LV_PART_MAIN| LV_STATE_DEFAULT);

ui_glob = lv_obj_create(ui_temperature);
lv_obj_set_width( ui_glob, 25);
lv_obj_set_height( ui_glob, 25);
lv_obj_set_x( ui_glob, 63 );
lv_obj_set_y( ui_glob, -19 );
lv_obj_set_align( ui_glob, LV_ALIGN_CENTER );
lv_obj_clear_flag( ui_glob, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | LV_OBJ_FLAG_SNAPPABLE | LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_ELASTIC | LV_OBJ_FLAG_SCROLL_MOMENTUM | LV_OBJ_FLAG_SCROLL_CHAIN );    /// Flags
lv_obj_set_style_bg_color(ui_glob, lv_color_hex(0x037DD9), LV_PART_MAIN | LV_STATE_DEFAULT );
lv_obj_set_style_bg_opa(ui_glob, 255, LV_PART_MAIN| LV_STATE_DEFAULT);
lv_obj_set_style_outline_color(ui_glob, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT );
lv_obj_set_style_outline_opa(ui_glob, 255, LV_PART_MAIN| LV_STATE_DEFAULT);
lv_obj_set_style_outline_width(ui_glob, 1, LV_PART_MAIN| LV_STATE_DEFAULT);
lv_obj_set_style_outline_pad(ui_glob, 1, LV_PART_MAIN| LV_STATE_DEFAULT);

ui_ampolla = lv_obj_create(ui_temperature);
lv_obj_set_width( ui_ampolla, 16);
lv_obj_set_height( ui_ampolla, 82);
lv_obj_set_x( ui_ampolla, 63 );
lv_obj_set_y( ui_ampolla, -56 );
lv_obj_set_align( ui_ampolla, LV_ALIGN_CENTER );
lv_obj_clear_flag( ui_ampolla, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | LV_OBJ_FLAG_SNAPPABLE | LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_ELASTIC | LV_OBJ_FLAG_SCROLL_MOMENTUM | LV_OBJ_FLAG_SCROLL_CHAIN );    /// Flags
lv_obj_set_style_border_color(ui_ampolla, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT );
lv_obj_set_style_border_opa(ui_ampolla, 255, LV_PART_MAIN| LV_STATE_DEFAULT);
lv_obj_set_style_border_width(ui_ampolla, 1, LV_PART_MAIN| LV_STATE_DEFAULT);

ui_glob1 = lv_obj_create(ui_temperature);
lv_obj_set_width( ui_glob1, 25);
lv_obj_set_height( ui_glob1, 25);
lv_obj_set_x( ui_glob1, 63 );
lv_obj_set_y( ui_glob1, -19 );
lv_obj_set_align( ui_glob1, LV_ALIGN_CENTER );
lv_obj_clear_flag( ui_glob1, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | LV_OBJ_FLAG_SNAPPABLE | LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_ELASTIC | LV_OBJ_FLAG_SCROLL_MOMENTUM | LV_OBJ_FLAG_SCROLL_CHAIN );    /// Flags
lv_obj_set_style_bg_color(ui_glob1, lv_color_hex(0x037DD9), LV_PART_MAIN | LV_STATE_DEFAULT );
lv_obj_set_style_bg_opa(ui_glob1, 255, LV_PART_MAIN| LV_STATE_DEFAULT);

ui_termometer = lv_bar_create(ui_temperature);
lv_bar_set_range(ui_termometer, 0,70);
lv_bar_set_value(ui_termometer,60,LV_ANIM_OFF);
lv_obj_set_width( ui_termometer, 10);
lv_obj_set_height( ui_termometer, 70);
lv_obj_set_x( ui_termometer, 63 );
lv_obj_set_y( ui_termometer, -58 );
lv_obj_set_align( ui_termometer, LV_ALIGN_CENTER );

lv_obj_set_style_bg_color(ui_termometer, lv_color_hex(0xD90368), LV_PART_INDICATOR | LV_STATE_DEFAULT );
lv_obj_set_style_bg_opa(ui_termometer, 255, LV_PART_INDICATOR| LV_STATE_DEFAULT);
lv_obj_set_style_bg_grad_color(ui_termometer, lv_color_hex(0x037DD9), LV_PART_INDICATOR | LV_STATE_DEFAULT );
lv_obj_set_style_bg_main_stop(ui_termometer, 100, LV_PART_INDICATOR| LV_STATE_DEFAULT);
lv_obj_set_style_bg_grad_stop(ui_termometer, 225, LV_PART_INDICATOR| LV_STATE_DEFAULT);
lv_obj_set_style_bg_grad_dir(ui_termometer, LV_GRAD_DIR_VER, LV_PART_INDICATOR| LV_STATE_DEFAULT);

ui_humidity = lv_arc_create(ui_Screen1);
lv_obj_set_width( ui_humidity, 230);
lv_obj_set_height( ui_humidity, 230);
lv_obj_set_align( ui_humidity, LV_ALIGN_CENTER );
lv_obj_clear_flag( ui_humidity, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | LV_OBJ_FLAG_SNAPPABLE | LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_ELASTIC | LV_OBJ_FLAG_SCROLL_MOMENTUM | LV_OBJ_FLAG_SCROLL_CHAIN );    /// Flags
lv_arc_set_value(ui_humidity, 20);
lv_arc_set_bg_angles(ui_humidity,0,100);
lv_arc_set_mode(ui_humidity, LV_ARC_MODE_REVERSE);
lv_arc_set_rotation(ui_humidity,75);

lv_obj_set_style_arc_color(ui_humidity, lv_color_hex(0x3C91E6), LV_PART_INDICATOR | LV_STATE_DEFAULT );
lv_obj_set_style_arc_opa(ui_humidity, 255, LV_PART_INDICATOR| LV_STATE_DEFAULT);

lv_obj_set_style_bg_color(ui_humidity, lv_color_hex(0x3C91E6), LV_PART_KNOB | LV_STATE_DEFAULT );
lv_obj_set_style_bg_opa(ui_humidity, 255, LV_PART_KNOB| LV_STATE_DEFAULT);
lv_obj_set_style_pad_left(ui_humidity, 0, LV_PART_KNOB| LV_STATE_DEFAULT);
lv_obj_set_style_pad_right(ui_humidity, 0, LV_PART_KNOB| LV_STATE_DEFAULT);
lv_obj_set_style_pad_top(ui_humidity, 0, LV_PART_KNOB| LV_STATE_DEFAULT);
lv_obj_set_style_pad_bottom(ui_humidity, 0, LV_PART_KNOB| LV_STATE_DEFAULT);

ui_humtxt = lv_label_create(ui_humidity);
lv_obj_set_width( ui_humtxt, LV_SIZE_CONTENT);  /// 1
lv_obj_set_height( ui_humtxt, LV_SIZE_CONTENT);   /// 1
lv_obj_set_x( ui_humtxt, -33 );
lv_obj_set_y( ui_humtxt, 54 );
lv_obj_set_align( ui_humtxt, LV_ALIGN_CENTER );
lv_label_set_text(ui_humtxt,"46%");
lv_obj_set_style_text_color(ui_humtxt, lv_color_hex(0x3C91E6), LV_PART_MAIN | LV_STATE_DEFAULT );
lv_obj_set_style_text_opa(ui_humtxt, 255, LV_PART_MAIN| LV_STATE_DEFAULT);
lv_obj_set_style_text_font(ui_humtxt, &lv_font_montserrat_40, LV_PART_MAIN| LV_STATE_DEFAULT);

ui_humCont = lv_obj_create(ui_humidity);
lv_obj_set_width( ui_humCont, 41);
lv_obj_set_height( ui_humCont, 50);
lv_obj_set_x( ui_humCont, 63 );
lv_obj_set_y( ui_humCont, 63 );
lv_obj_set_align( ui_humCont, LV_ALIGN_CENTER );
lv_obj_clear_flag( ui_humCont, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | LV_OBJ_FLAG_SNAPPABLE | LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_ELASTIC | LV_OBJ_FLAG_SCROLL_MOMENTUM | LV_OBJ_FLAG_SCROLL_CHAIN );    /// Flags
lv_obj_set_style_border_color(ui_humCont, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT );
lv_obj_set_style_border_opa(ui_humCont, 255, LV_PART_MAIN| LV_STATE_DEFAULT);
lv_obj_set_style_border_width(ui_humCont, 2, LV_PART_MAIN| LV_STATE_DEFAULT);

ui_humBar = lv_bar_create(ui_humCont);
lv_bar_set_value(ui_humBar,60,LV_ANIM_OFF);
lv_obj_set_width( ui_humBar, 50);
lv_obj_set_height( ui_humBar, 52);
lv_obj_set_align( ui_humBar, LV_ALIGN_CENTER );
lv_obj_set_style_radius(ui_humBar, 0, LV_PART_MAIN| LV_STATE_DEFAULT);
lv_obj_set_style_bg_color(ui_humBar, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT );
lv_obj_set_style_bg_opa(ui_humBar, 0, LV_PART_MAIN| LV_STATE_DEFAULT);

lv_obj_set_style_radius(ui_humBar, 20, LV_PART_INDICATOR| LV_STATE_DEFAULT);
lv_obj_set_style_bg_color(ui_humBar, lv_color_hex(0x2F98E2), LV_PART_INDICATOR | LV_STATE_DEFAULT );
lv_obj_set_style_bg_opa(ui_humBar, 255, LV_PART_INDICATOR| LV_STATE_DEFAULT);

ui_Panel1 = lv_obj_create(ui_Screen1);
lv_obj_set_width( ui_Panel1, 4);
lv_obj_set_height( ui_Panel1, 4);
lv_obj_set_x( ui_Panel1, 62 );
lv_obj_set_y( ui_Panel1, 76 );
lv_obj_set_align( ui_Panel1, LV_ALIGN_CENTER );
lv_obj_clear_flag( ui_Panel1, LV_OBJ_FLAG_SCROLLABLE );    /// Flags
lv_obj_set_style_radius(ui_Panel1, 4, LV_PART_MAIN| LV_STATE_DEFAULT);
lv_obj_set_style_bg_color(ui_Panel1, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT );
lv_obj_set_style_bg_opa(ui_Panel1, 0, LV_PART_MAIN| LV_STATE_DEFAULT);
lv_obj_set_style_border_width(ui_Panel1, 1, LV_PART_MAIN| LV_STATE_DEFAULT);

ui_Panel2 = lv_obj_create(ui_Screen1);
lv_obj_set_width( ui_Panel2, 5);
lv_obj_set_height( ui_Panel2, 5);
lv_obj_set_x( ui_Panel2, 65 );
lv_obj_set_y( ui_Panel2, 69 );
lv_obj_set_align( ui_Panel2, LV_ALIGN_CENTER );
lv_obj_clear_flag( ui_Panel2, LV_OBJ_FLAG_SCROLLABLE );    /// Flags
lv_obj_set_style_radius(ui_Panel2, 5, LV_PART_MAIN| LV_STATE_DEFAULT);
lv_obj_set_style_bg_color(ui_Panel2, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT );
lv_obj_set_style_bg_opa(ui_Panel2, 0, LV_PART_MAIN| LV_STATE_DEFAULT);
lv_obj_set_style_border_width(ui_Panel2, 1, LV_PART_MAIN| LV_STATE_DEFAULT);

ui_Panel3 = lv_obj_create(ui_Screen1);
lv_obj_set_width( ui_Panel3, 7);
lv_obj_set_height( ui_Panel3, 7);
lv_obj_set_x( ui_Panel3, 62 );
lv_obj_set_y( ui_Panel3, 59 );
lv_obj_set_align( ui_Panel3, LV_ALIGN_CENTER );
lv_obj_clear_flag( ui_Panel3, LV_OBJ_FLAG_SCROLLABLE );    /// Flags
lv_obj_set_style_radius(ui_Panel3, 7, LV_PART_MAIN| LV_STATE_DEFAULT);
lv_obj_set_style_bg_color(ui_Panel3, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT );
lv_obj_set_style_bg_opa(ui_Panel3, 0, LV_PART_MAIN| LV_STATE_DEFAULT);
lv_obj_set_style_border_width(ui_Panel3, 1, LV_PART_MAIN| LV_STATE_DEFAULT);

ui_Panel4 = lv_obj_create(ui_Screen1);
lv_obj_set_width( ui_Panel4, 10);
lv_obj_set_height( ui_Panel4, 10);
lv_obj_set_x( ui_Panel4, 69 );
lv_obj_set_y( ui_Panel4, 52 );
lv_obj_set_align( ui_Panel4, LV_ALIGN_CENTER );
lv_obj_clear_flag( ui_Panel4, LV_OBJ_FLAG_SCROLLABLE );    /// Flags
lv_obj_set_style_radius(ui_Panel4, 9, LV_PART_MAIN| LV_STATE_DEFAULT);
lv_obj_set_style_bg_color(ui_Panel4, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT );
lv_obj_set_style_bg_opa(ui_Panel4, 0, LV_PART_MAIN| LV_STATE_DEFAULT);
lv_obj_set_style_border_width(ui_Panel4, 1, LV_PART_MAIN| LV_STATE_DEFAULT);

ui_Panel5 = lv_obj_create(ui_Screen1);
lv_obj_set_width( ui_Panel5, 10);
lv_obj_set_height( ui_Panel5, 10);
lv_obj_set_x( ui_Panel5, 55 );
lv_obj_set_y( ui_Panel5, 50 );
lv_obj_set_align( ui_Panel5, LV_ALIGN_CENTER );
lv_obj_clear_flag( ui_Panel5, LV_OBJ_FLAG_SCROLLABLE );    /// Flags
lv_obj_set_style_radius(ui_Panel5, 9, LV_PART_MAIN| LV_STATE_DEFAULT);
lv_obj_set_style_bg_color(ui_Panel5, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT );
lv_obj_set_style_bg_opa(ui_Panel5, 0, LV_PART_MAIN| LV_STATE_DEFAULT);
lv_obj_set_style_border_width(ui_Panel5, 1, LV_PART_MAIN| LV_STATE_DEFAULT);


}

but after some time my screen get frozen but the processor and the serial print on my terminal continue correctly.
I’m using esp32 wroowe kit and a 1.28 inch round lcd with gc9a01 driver.

here my initialization code:
display.c to install SPI and GPIO



/* INCLUDES ------------------------------------------------------------------*/
#include "display.h"


/* PRIVATE STRUCTRES ---------------------------------------------------------*/

/* VARIABLES -----------------------------------------------------------------*/
lv_disp_drv_t disp_drv;  // contains callback functions
/* DEFINITIONS ---------------------------------------------------------------*/

/* MACROS --------------------------------------------------------------------*/
static const char *TAG = "display";
/* PRIVATE FUNCTIONS DECLARATION ---------------------------------------------*/
extern void ui_init();

/* FUNCTION PROTOTYPES -------------------------------------------------------*/


bool display_notify_lvgl_flush_ready(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_io_event_data_t *edata, void *user_ctx)
{
    lv_disp_drv_t *disp_driver = (lv_disp_drv_t *)user_ctx;
    lv_disp_flush_ready(disp_driver);
    return false;
}

static void example_lvgl_flush_cb(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map)
{
    esp_lcd_panel_handle_t panel_handle = (esp_lcd_panel_handle_t) drv->user_data;
    int offsetx1 = area->x1;
    int offsetx2 = area->x2;
    int offsety1 = area->y1;
    int offsety2 = area->y2;
    // copy a buffer's content to a specific area of the display
    esp_lcd_panel_draw_bitmap(panel_handle, offsetx1, offsety1, offsetx2 + 1, offsety2 + 1, color_map);
}

/* Rotate display and touch, when rotated screen in LVGL. Called when driver parameters are updated. */
static void example_lvgl_port_update_callback(lv_disp_drv_t *drv)
{
    esp_lcd_panel_handle_t panel_handle = (esp_lcd_panel_handle_t) drv->user_data;

    switch (drv->rotated) {
    case LV_DISP_ROT_NONE:
        // Rotate LCD display
        esp_lcd_panel_swap_xy(panel_handle, false);
        esp_lcd_panel_mirror(panel_handle, true, false);

        break;
    case LV_DISP_ROT_90:
        // Rotate LCD display
        esp_lcd_panel_swap_xy(panel_handle, true);
        esp_lcd_panel_mirror(panel_handle, true, true);

        break;
    case LV_DISP_ROT_180:
        // Rotate LCD display
        esp_lcd_panel_swap_xy(panel_handle, false);
        esp_lcd_panel_mirror(panel_handle, false, true);

        break;
    case LV_DISP_ROT_270:
        // Rotate LCD display
        esp_lcd_panel_swap_xy(panel_handle, true);
        esp_lcd_panel_mirror(panel_handle, false, false);

        break;
    }
}



static void example_increase_lvgl_tick(void *arg)
{
    /* Tell LVGL how many milliseconds has elapsed */
    lv_tick_inc(EXAMPLE_LVGL_TICK_PERIOD_MS);
}


void displayConfig(void)
{
    static lv_disp_draw_buf_t disp_buf; // contains internal graphic buffer(s) called draw buffer(s)




    ESP_LOGI(TAG, "Initialize LVGL library");
    lv_init();
    // alloc draw buffers used by LVGL
    // it's recommended to choose the size of the draw buffer(s) to be at least 1/10 screen sized
    lv_color_t *buf1 = heap_caps_malloc(EXAMPLE_LCD_H_RES * 30 * sizeof(lv_color_t), MALLOC_CAP_DMA);
    assert(buf1);
    lv_color_t *buf2 = heap_caps_malloc(EXAMPLE_LCD_H_RES * 30 * sizeof(lv_color_t), MALLOC_CAP_DMA);
    assert(buf2);
    // initialize LVGL draw buffers
    lv_disp_draw_buf_init(&disp_buf, buf1, buf2, EXAMPLE_LCD_H_RES * 30);

    ESP_LOGI(TAG, "Register display driver to LVGL");
    lv_disp_drv_init(&disp_drv);
    disp_drv.hor_res = EXAMPLE_LCD_H_RES;
    disp_drv.ver_res = EXAMPLE_LCD_V_RES;
    disp_drv.flush_cb = example_lvgl_flush_cb;
    disp_drv.drv_update_cb = example_lvgl_port_update_callback;
    disp_drv.draw_buf = &disp_buf;
    disp_drv.user_data = panel_handle;
    lv_disp_t *disp = lv_disp_drv_register(&disp_drv);

    ESP_LOGI(TAG, "Install LVGL tick timer");
    // Tick interface for LVGL (using esp_timer to generate 2ms periodic event)
    const esp_timer_create_args_t lvgl_tick_timer_args = {
        .callback = &example_increase_lvgl_tick,
        .name = "lvgl_tick"
    };
    esp_timer_handle_t lvgl_tick_timer = NULL;
    ESP_ERROR_CHECK(esp_timer_create(&lvgl_tick_timer_args, &lvgl_tick_timer));
    ESP_ERROR_CHECK(esp_timer_start_periodic(lvgl_tick_timer, EXAMPLE_LVGL_TICK_PERIOD_MS * 1000));


    ESP_LOGI(TAG, "Display LVGL MySensor Widget");
    ui_init(disp);

}

hera the gc9a01 configuration file to allocate buffers and start tick counter


/* INCLUDES ------------------------------------------------------------------*/
#include "gc9a01.h"
#include "display.h"
/* PRIVATE STRUCTRES ---------------------------------------------------------*/

/* VARIABLES -----------------------------------------------------------------*/

static const char *gc9a01 = "display";

esp_lcd_panel_handle_t panel_handle = NULL;
/* DEFINITIONS ---------------------------------------------------------------*/

/* MACROS --------------------------------------------------------------------*/

/* PRIVATE FUNCTIONS DECLARATION ---------------------------------------------*/

/* FUNCTION PROTOTYPES -------------------------------------------------------*/
void gc9a01_displayInit(void)
{
    ESP_LOGI(gc9a01, "Turn off LCD backlight");
    gpio_config_t bk_gpio_config = {
        .mode = GPIO_MODE_OUTPUT,
        .pin_bit_mask = 1ULL << EXAMPLE_PIN_NUM_BK_LIGHT
    };
    ESP_ERROR_CHECK(gpio_config(&bk_gpio_config));

    ESP_LOGI(gc9a01, "Initialize SPI bus");
    spi_bus_config_t buscfg = {
        .sclk_io_num = EXAMPLE_PIN_NUM_SCLK,
        .mosi_io_num = EXAMPLE_PIN_NUM_MOSI,
        .miso_io_num = EXAMPLE_PIN_NUM_MISO,
        .quadwp_io_num = -1,
        .quadhd_io_num = -1,
        .max_transfer_sz = EXAMPLE_LCD_H_RES * 80 * sizeof(uint16_t),
    };
    ESP_ERROR_CHECK(spi_bus_initialize(LCD_HOST, &buscfg, SPI_DMA_CH_AUTO));

    ESP_LOGI(gc9a01, "Install panel IO");
    esp_lcd_panel_io_handle_t io_handle = NULL;
    esp_lcd_panel_io_spi_config_t io_config = {
        .dc_gpio_num = EXAMPLE_PIN_NUM_LCD_DC,
        .cs_gpio_num = EXAMPLE_PIN_NUM_LCD_CS,
        .pclk_hz = EXAMPLE_LCD_PIXEL_CLOCK_HZ,
        .lcd_cmd_bits = EXAMPLE_LCD_CMD_BITS,
        .lcd_param_bits = EXAMPLE_LCD_PARAM_BITS,
        .spi_mode = 0,
        .trans_queue_depth = 10,
        .on_color_trans_done = display_notify_lvgl_flush_ready,
        .user_ctx = &disp_drv,
    };
    // Attach the LCD to the SPI bus
    ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)LCD_HOST, &io_config, &io_handle));

    ESP_LOGI(gc9a01, "Install GC9A01 panel driver");

    esp_lcd_panel_dev_config_t panel_config = {
        .reset_gpio_num = EXAMPLE_PIN_NUM_LCD_RST,

        .rgb_endian = LCD_RGB_ENDIAN_RGB,

        .rgb_endian = LCD_RGB_ENDIAN_BGR,

        .bits_per_pixel = 16,
    };


    ESP_ERROR_CHECK(esp_lcd_new_panel_gc9a01(io_handle, &panel_config, &panel_handle));


    ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle));
    ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle));

    ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel_handle, true));

    ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, true, false));

    // user can flush pre-defined pattern to the screen before we turn on the screen or backlight
    ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true));


    ESP_LOGI(gc9a01, "Turn on LCD backlight");
    gpio_set_level(EXAMPLE_PIN_NUM_BK_LIGHT, EXAMPLE_LCD_BK_LIGHT_ON_LEVEL);


}

/*************************************** USEFUL ELECTRONICS*****END OF FILE****/

the last is my main file used to test the display:

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_timer.h"
#include "esp_heap_task_info.h"
#include "display/display.h"
#include "display/gc9a01.h"
#include "display/ui_helpers.h"



/* PRIVATE STRUCTRES ---------------------------------------------------------*/
#define MAX_TASK_NUM 20                         // Max number of per tasks info that it can store
#define MAX_BLOCK_NUM 20                        // Max number of per block info that it can store


/* VARIABLES -----------------------------------------------------------------*/
static const char *TAG = "main";
/* DEFINITIONS ---------------------------------------------------------------*/

/* MACROS --------------------------------------------------------------------*/

/* PRIVATE FUNCTIONS DECLARATION ---------------------------------------------*/
static void lvgl_time_task(void*param);
static void lvgl_display_task(void* param);
/* FUNCTION PROTOTYPES -------------------------------------------------------*/

void app_main(void)
{

	ESP_LOGI(TAG, "Start Main");

	gc9a01_displayInit();
	displayConfig();   

 	xTaskCreatePinnedToCore(lvgl_time_task, "lvgl_time_task", 2048*5, NULL, 3, NULL, 1);
 	xTaskCreatePinnedToCore(lvgl_display_task, "lvgl_display_task", 2048*5, NULL, 4, NULL, 1);

}


/**
 * @brief 	LVGL library timer task. Necessary to run once every 10ms
 *
 */
void lvgl_time_task(void* param)
{
	ESP_LOGI(TAG, "TIME Task");
	TickType_t xLastWakeTime = xTaskGetTickCount();

	while(1)
	{
        // The task running lv_timer_handler should have lower priority than that running `lv_tick_inc`
        lv_timer_handler();
        vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(10) );
	}
}


void lvgl_display_task(void* param)
{

	ESP_LOGI(TAG, "display task");
	TickType_t xLastWakeTime = xTaskGetTickCount();
	char str[8];
	

	static uint16_t counter=0;
	uint16_t temp_value;
	uint16_t hum_value;
	while(1)
	{
		vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(1000) );

		//---temperature update
			temp_value = counter % 60;
			hum_value = counter  % 100;

			lv_obj_set_height( ui_TempIndicator,counter%110 );
			lv_arc_set_value(ui_temperature, temp_value);
			lv_bar_set_value(ui_termometer, temp_value,LV_ANIM_OFF);
			
			sprintf(str, "%d °C", temp_value);
			_ui_label_set_property( ui_temptxt, _UI_LABEL_PROPERTY_TEXT, str);
			//ESP_LOGI(TAG, "Updates element Temp %d",temp_value);

		//--- humidity update
			lv_obj_set_height( ui_HumIndicator, counter % 140);			
			lv_arc_set_value(ui_humidity, hum_value);
			lv_bar_set_value(ui_humBar, hum_value,LV_ANIM_ON);
			sprintf(str, "%d %%", hum_value);
			_ui_label_set_property( ui_humtxt, _UI_LABEL_PROPERTY_TEXT, str);
			//ESP_LOGI(TAG, "Updates element Hum %d",hum_value);
			
		counter++;	
	}
}

What have you tried so far?

I tried to attach jtag debugger but with no success to understand the issue.
the screen get stuck after several cycles (400), I tried to analyze the heap memory but this does not seem the cause.
do you have any suggestion or tips?
thank you.

Screenshot or video

Others

  • SquareLine Studio version: 1.3.2
  • Operating system: windows 11
  • Target hardware: esp32 + round 1.28 lcd gc9a01 driver

SOLVED

I think I have solved my Issue with the frozen screen.
I started with logging LVGS data with the dedicated flag and printf and i noticed that when the screen get stuck the log reports a corruption in memory.
So I started searching and I found that ** LVGL is not thread-safe by default.** as reported HERE
This is why I started SemaphoreHandle_t xSemaphore function and Mutex https://www.freertos.org/CreateMutex.html but the error was always here.
This is because ESP32 has 2 CORES and I was initializing display and GC9a01 drivers on CORE 0 but my tasks were running on CORE 1 because I was planning to use WIFI that runs on CORE 0.
INDEED with the following CODE my screen Is not freezing an I can choose where to run the LVGL LIBRARY (always with the MANDATORY OPTION to run initialization and tasks on the same CORE)

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "freertos/task.h"
#include "esp_timer.h"
#include "esp_heap_task_info.h"
#include "display/display.h"
#include "display/gc9a01.h"
#include "display/ui_helpers.h"



/* PRIVATE STRUCTRES ---------------------------------------------------------*/
#define MAX_TASK_NUM 20                         // Max number of per tasks info that it can store
#define MAX_BLOCK_NUM 20                        // Max number of per block info that it can store


/* VARIABLES -----------------------------------------------------------------*/
static const char *TAG = "main";
/* DEFINITIONS ---------------------------------------------------------------*/

/* MACROS --------------------------------------------------------------------*/

/* PRIVATE FUNCTIONS DECLARATION ---------------------------------------------*/
static void lvgl_time_task(void*param);
static void lvgl_display_task(void* param);
/* FUNCTION PROTOTYPES -------------------------------------------------------*/
UBaseType_t uxHighWaterMark;
/* Creates a semaphore to handle concurrent call to lvgl stuff
 * If you wish to call *any* lvgl function from other threads/tasks
 * you should lock on the very same semaphore! */
SemaphoreHandle_t xSemaphore = NULL;

    


void app_main(void)
{
		// Create the semaphore to guard a shared resource.  As we are using
    // the semaphore for mutual exclusion we create a mutex semaphore
    // rather than a binary semaphore.
	xSemaphore = xSemaphoreCreateMutex();

	ESP_LOGI(TAG, "Start Main");

	 

 	xTaskCreatePinnedToCore(lvgl_time_task, "lvgl_time_task", 2048*4, NULL, 3, NULL, 1);
	vTaskDelay(5000/portTICK_PERIOD_MS);
 	xTaskCreatePinnedToCore(lvgl_display_task, "lvgl_display_task", 2048*2, NULL, 4, NULL, 1);

}


/**
 * @brief 	LVGL library timer task. Necessary to run once every 10ms
 *
 */
void lvgl_time_task(void* param)
{
	ESP_LOGI(TAG, "TIME Task");
/* Inspect our own high water mark on entering the task. */
        uxHighWaterMark = uxTaskGetStackHighWaterMark( NULL );
        printf("lvgl_time_task Stack is near: %p \r\n",  (void *)uxHighWaterMark);

	gc9a01_displayInit();
	uxHighWaterMark = uxTaskGetStackHighWaterMark( NULL );
        printf("gc9a01_displayInit Stack is near: %p \r\n",  (void *)uxHighWaterMark);
	displayConfig(); 
	
	uxHighWaterMark = uxTaskGetStackHighWaterMark( NULL );
        printf("displayConfig Stack is near: %p \r\n",  (void *)uxHighWaterMark);

	(void)param;
	TickType_t xLastWakeTime = xTaskGetTickCount();

	while(1)
	{
		/* Delay 1 tick (assumes FreeRTOS tick is 10ms */
    	vTaskDelay(pdMS_TO_TICKS(10));

		if (xSemaphoreTake(xSemaphore, ( TickType_t ) 10 ) == pdTRUE)
		{
			lv_task_handler();
			/* We have finished accessing the shared resource.  Release the
            semaphore. */
			xSemaphoreGive(xSemaphore);
		}else
        {
            /* We could not obtain the semaphore and can therefore not access
            the shared resource safely. */
			ESP_LOGI(TAG, "TIME Task Waiting Semaphore");
        }
	}
	  /* A task should NEVER return */
	vTaskDelete(NULL);

}


void lvgl_display_task(void* param)
{
	TickType_t xLastWakeTime = xTaskGetTickCount();
	char str[8];
	

	static uint16_t counter=0;
	uint16_t temp_value;
	uint16_t hum_value;
	while(1)
	{
		vTaskDelay(100/portTICK_PERIOD_MS);

		/* See if we can obtain the semaphore.  If the semaphore is not
        available wait 10 ticks to see if it becomes free. */
		if (xSemaphoreTake(xSemaphore, ( TickType_t ) 10 ) == pdTRUE)
		{
			//---temperature update
				temp_value = counter % 60;
				hum_value = counter  % 100;

				lv_obj_set_height( ui_TempIndicator,counter%110 );
				lv_arc_set_value(ui_temperature, temp_value);
				lv_bar_set_value(ui_termometer, temp_value,LV_ANIM_OFF);
				
				sprintf(str, "%d °C", temp_value);
				_ui_label_set_property( ui_temptxt, _UI_LABEL_PROPERTY_TEXT, str);
				//ESP_LOGI(TAG, "Updates element Temp %d",temp_value);

			//--- humidity update
				lv_obj_set_height( ui_HumIndicator, counter % 140);			
				lv_arc_set_value(ui_humidity, hum_value);
				lv_bar_set_value(ui_humBar, hum_value,LV_ANIM_OFF);
				sprintf(str, "%d %%", hum_value);
				_ui_label_set_property( ui_humtxt, _UI_LABEL_PROPERTY_TEXT, str);
				//ESP_LOGI(TAG, "Updates element Hum %d",hum_value);
						
			counter++;
			xSemaphoreGive(xSemaphore);	
		}else
        {
            /* We could not obtain the semaphore and can therefore not access
            the shared resource safely. */
			ESP_LOGI(TAG, "lvgl_display_task Task Waiting Semaphore");
        }
	}

	/* A task should NEVER return */
	vTaskDelete(NULL);
}

The working TIP is here :

 	xTaskCreatePinnedToCore(lvgl_time_task, "lvgl_time_task", 2048*4, NULL, 3, NULL, 1);
 	xTaskCreatePinnedToCore(lvgl_display_task, "lvgl_display_task", 2048*2, NULL, 4, NULL, 1);

these two TASKS have to be on the same CORE, in this test are on CORE 1 but everything works also on CORE 0.

Hello rebel,

I habe same issure my system work very well buy after 3 or 4 hours or any time the screen can be frozen but esp32 continue to work for other fontions.

What will you suggest is your solution still be valid for me.?

Thanks

I have
void loop()
{
lv_timer_handler(); /* let the GUI do its work */
delay(50);
}

and i have other tasks pinned to core 1 running.

May be i do mistake?
what do you think.

Thanks

We think, that not mistake when your gui do nothink, but when you have lv code in other tasks … next boy , that not read docu, or girl…

It’s sure, LVGL is not thread-safe by default, so programmers must be careful about guarding common resources used by different cores/threads against race-conditions. (Freezes can be caused by problems with this, just like by LV_MEM_CUSTOM/LV_MEM_SIZE settings in lv_conf.h.)

I have deleted one task to reduce some work ,and now system looks stable i hope it will continue. but facing some other problems with objects udates.

I will see lv_confi.h

Thanks for time .

Thanks for your anwer i will investigate and check.I start with deleting some tasks.

Primary change not delete tasks. Read Operating system and interrupts — LVGL documentation