fix: lv_deinit/lv_init crash or hang (#2910)

* Fix themes that are not correctly initialized after lv_deinit

* Fix performance & memory monitoring not correctly initialized after lv_deinit & lv_init

* Apply code formatting fixes

* Fix build errors

* Fix build errors

* Fix formatting

Co-authored-by: Gabor Kiss-Vamosi <kisvegabor@gmail.com>
This commit is contained in:
geert-KLA-BE
2021-12-20 14:05:06 +01:00
committed by GitHub
parent e24a9fdf18
commit 6e00724797
6 changed files with 138 additions and 49 deletions

View File

@@ -29,6 +29,23 @@
/********************** /**********************
* TYPEDEFS * TYPEDEFS
**********************/ **********************/
typedef struct {
uint32_t perf_last_time;
uint32_t elaps_sum;
uint32_t frame_cnt;
uint32_t fps_sum_cnt;
uint32_t fps_sum_all;
#if LV_USE_LABEL
lv_obj_t * perf_label;
#endif
} perf_monitor_t;
typedef struct {
uint32_t mem_last_time;
#if LV_USE_LABEL
lv_obj_t * mem_label;
#endif
} mem_monitor_t;
/********************** /**********************
* STATIC PROTOTYPES * STATIC PROTOTYPES
@@ -43,14 +60,25 @@ static void lv_refr_obj(lv_obj_t * obj, const lv_area_t * mask_ori_p);
static void draw_buf_flush(void); static void draw_buf_flush(void);
static void call_flush_cb(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_p); static void call_flush_cb(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_p);
#if LV_USE_PERF_MONITOR
static void perf_monitor_init(perf_monitor_t * perf_monitor);
#endif
#if LV_USE_MEM_MONITOR
static void mem_monitor_init(mem_monitor_t * mem_monitor);
#endif
/********************** /**********************
* STATIC VARIABLES * STATIC VARIABLES
**********************/ **********************/
static uint32_t px_num; static uint32_t px_num;
static lv_disp_t * disp_refr; /*Display being refreshed*/ static lv_disp_t * disp_refr; /*Display being refreshed*/
#if LV_USE_PERF_MONITOR #if LV_USE_PERF_MONITOR
static uint32_t fps_sum_cnt; static perf_monitor_t perf_monitor;
static uint32_t fps_sum_all; #endif
#if LV_USE_MEM_MONITOR
static mem_monitor_t mem_monitor;
#endif #endif
/********************** /**********************
@@ -71,7 +99,12 @@ static lv_disp_t * disp_refr; /*Display being refreshed*/
*/ */
void _lv_refr_init(void) void _lv_refr_init(void)
{ {
/*Nothing to do*/ #if LV_USE_PERF_MONITOR
perf_monitor_init(&perf_monitor);
#endif
#if LV_USE_MEM_MONITOR
mem_monitor_init(&mem_monitor);
#endif
} }
/** /**
@@ -245,7 +278,7 @@ void _lv_disp_refr_timer(lv_timer_t * tmr)
#endif #endif
#if LV_USE_PERF_MONITOR && LV_USE_LABEL #if LV_USE_PERF_MONITOR && LV_USE_LABEL
static lv_obj_t * perf_label = NULL; lv_obj_t * perf_label = perf_monitor.perf_label;
if(perf_label == NULL) { if(perf_label == NULL) {
perf_label = lv_label_create(lv_layer_sys()); perf_label = lv_label_create(lv_layer_sys());
lv_obj_set_style_bg_opa(perf_label, LV_OPA_50, 0); lv_obj_set_style_bg_opa(perf_label, LV_OPA_50, 0);
@@ -260,36 +293,41 @@ void _lv_disp_refr_timer(lv_timer_t * tmr)
lv_obj_align(perf_label, LV_USE_PERF_MONITOR_POS, 0, 0); lv_obj_align(perf_label, LV_USE_PERF_MONITOR_POS, 0, 0);
} }
static uint32_t perf_last_time = 0; if(lv_tick_elaps(perf_monitor.perf_last_time) < 300) {
static uint32_t elaps_sum = 0;
static uint32_t frame_cnt = 0;
if(lv_tick_elaps(perf_last_time) < 300) {
if(px_num > 5000) { if(px_num > 5000) {
elaps_sum += elaps; perf_monitor.elaps_sum += elaps;
frame_cnt ++; perf_monitor.frame_cnt ++;
} }
} }
else { else {
perf_last_time = lv_tick_get(); perf_monitor.perf_last_time = lv_tick_get();
uint32_t fps_limit = 1000 / disp_refr->refr_timer->period; uint32_t fps_limit = 1000 / disp_refr->refr_timer->period;
uint32_t fps; uint32_t fps;
if(elaps_sum == 0) elaps_sum = 1; if(perf_monitor.elaps_sum == 0) {
if(frame_cnt == 0) fps = fps_limit; perf_monitor.elaps_sum = 1;
else fps = (1000 * frame_cnt) / elaps_sum; }
elaps_sum = 0; if(perf_monitor.frame_cnt == 0) {
frame_cnt = 0; fps = fps_limit;
if(fps > fps_limit) fps = fps_limit; }
else {
fps = (1000 * perf_monitor.frame_cnt) / perf_monitor.elaps_sum;
}
perf_monitor.elaps_sum = 0;
perf_monitor.frame_cnt = 0;
if(fps > fps_limit) {
fps = fps_limit;
}
fps_sum_all += fps; perf_monitor.fps_sum_all += fps;
fps_sum_cnt ++; perf_monitor.fps_sum_cnt ++;
uint32_t cpu = 100 - lv_timer_get_idle(); uint32_t cpu = 100 - lv_timer_get_idle();
lv_label_set_text_fmt(perf_label, "%"LV_PRIu32" FPS\n%"LV_PRIu32"%% CPU", fps, cpu); lv_label_set_text_fmt(perf_label, "%"LV_PRIu32" FPS\n%"LV_PRIu32"%% CPU", fps, cpu);
} }
#endif #endif
#if LV_USE_MEM_MONITOR && LV_MEM_CUSTOM == 0 && LV_USE_LABEL #if LV_USE_MEM_MONITOR && LV_MEM_CUSTOM == 0 && LV_USE_LABEL
static lv_obj_t * mem_label = NULL; lv_obj_t * mem_label = mem_monitor.mem_label;
if(mem_label == NULL) { if(mem_label == NULL) {
mem_label = lv_label_create(lv_layer_sys()); mem_label = lv_label_create(lv_layer_sys());
lv_obj_set_style_bg_opa(mem_label, LV_OPA_50, 0); lv_obj_set_style_bg_opa(mem_label, LV_OPA_50, 0);
@@ -303,9 +341,8 @@ void _lv_disp_refr_timer(lv_timer_t * tmr)
lv_obj_align(mem_label, LV_USE_MEM_MONITOR_POS, 0, 0); lv_obj_align(mem_label, LV_USE_MEM_MONITOR_POS, 0, 0);
} }
static uint32_t mem_last_time = 0; if(lv_tick_elaps(mem_monitor.mem_last_time) > 300) {
if(lv_tick_elaps(mem_last_time) > 300) { mem_monitor.mem_last_time = lv_tick_get();
mem_last_time = lv_tick_get();
lv_mem_monitor_t mon; lv_mem_monitor_t mon;
lv_mem_monitor(&mon); lv_mem_monitor(&mon);
uint32_t used_size = mon.total_size - mon.free_size;; uint32_t used_size = mon.total_size - mon.free_size;;
@@ -323,16 +360,16 @@ void _lv_disp_refr_timer(lv_timer_t * tmr)
#if LV_USE_PERF_MONITOR #if LV_USE_PERF_MONITOR
void lv_refr_reset_fps_counter(void) void lv_refr_reset_fps_counter(void)
{ {
fps_sum_all = 0; perf_monitor.fps_sum_all = 0;
fps_sum_cnt = 0; perf_monitor.fps_sum_cnt = 0;
} }
uint32_t lv_refr_get_fps_avg(void) uint32_t lv_refr_get_fps_avg(void)
{ {
if(fps_sum_cnt == 0) if(perf_monitor.fps_sum_cnt == 0) {
return 0; return 0;
}
return fps_sum_all / fps_sum_cnt; return perf_monitor.fps_sum_all / perf_monitor.fps_sum_cnt;
} }
#endif #endif
@@ -1002,3 +1039,26 @@ static void call_flush_cb(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_
drv->flush_cb(drv, &offset_area, color_p); drv->flush_cb(drv, &offset_area, color_p);
} }
#if LV_USE_PERF_MONITOR
static void perf_monitor_init(perf_monitor_t * _perf_monitor)
{
LV_ASSERT_NULL(_perf_monitor);
_perf_monitor->elaps_sum = 0;
_perf_monitor->fps_sum_all = 0;
_perf_monitor->fps_sum_cnt = 0;
_perf_monitor->frame_cnt = 0;
_perf_monitor->perf_last_time = 0;
_perf_monitor->perf_label = NULL;
}
#endif
#if LV_USE_MEM_MONITOR
static void mem_monitor_init(mem_monitor_t * _mem_monitor)
{
LV_ASSERT_NULL(_mem_monitor);
_mem_monitor->mem_last_time = 0;
_mem_monitor->mem_label = NULL;
}
#endif

View File

@@ -50,7 +50,6 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj);
**********************/ **********************/
static my_theme_styles_t * styles; static my_theme_styles_t * styles;
static lv_theme_t theme; static lv_theme_t theme;
static bool inited;
/********************** /**********************
* MACROS * MACROS
@@ -120,13 +119,18 @@ static void style_init(void)
* GLOBAL FUNCTIONS * GLOBAL FUNCTIONS
**********************/ **********************/
bool lv_theme_basic_is_inited(void)
{
return LV_GC_ROOT(_lv_theme_default_styles) == NULL ? false : true;
}
lv_theme_t * lv_theme_basic_init(lv_disp_t * disp) lv_theme_t * lv_theme_basic_init(lv_disp_t * disp)
{ {
/*This trick is required only to avoid the garbage collection of /*This trick is required only to avoid the garbage collection of
*styles' data if LVGL is used in a binding (e.g. Micropython) *styles' data if LVGL is used in a binding (e.g. Micropython)
*In a general case styles could be in simple `static lv_style_t my_style...` variables*/ *In a general case styles could be in simple `static lv_style_t my_style...` variables*/
if(!inited) { if(!lv_theme_basic_is_inited()) {
LV_GC_ROOT(_lv_theme_default_styles) = lv_mem_alloc(sizeof(my_theme_styles_t)); LV_GC_ROOT(_lv_theme_default_styles) = lv_mem_alloc(sizeof(my_theme_styles_t));
styles = (my_theme_styles_t *)LV_GC_ROOT(_lv_theme_default_styles); styles = (my_theme_styles_t *)LV_GC_ROOT(_lv_theme_default_styles);
} }
@@ -139,9 +143,9 @@ lv_theme_t * lv_theme_basic_init(lv_disp_t * disp)
style_init(); style_init();
inited = true; if(disp == NULL || lv_disp_get_theme(disp) == &theme) {
lv_obj_report_style_change(NULL);
if(disp == NULL || lv_disp_get_theme(disp) == &theme) lv_obj_report_style_change(NULL); }
return (lv_theme_t *)&theme; return (lv_theme_t *)&theme;
} }
@@ -375,8 +379,12 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj)
static void style_init_reset(lv_style_t * style) static void style_init_reset(lv_style_t * style)
{ {
if(inited) lv_style_reset(style); if(lv_theme_basic_is_inited()) {
else lv_style_init(style); lv_style_reset(style);
}
else {
lv_style_init(style);
}
} }
#endif #endif

View File

@@ -36,6 +36,12 @@ extern "C" {
*/ */
lv_theme_t * lv_theme_basic_init(lv_disp_t * disp); lv_theme_t * lv_theme_basic_init(lv_disp_t * disp);
/**
* Check if the theme is initialized
* @return true if default theme is initialized, false otherwise
*/
bool lv_theme_basic_is_inited(void);
/********************** /**********************
* MACROS * MACROS
**********************/ **********************/

View File

@@ -173,7 +173,6 @@ static void style_init_reset(lv_style_t * style);
static my_theme_styles_t * styles; static my_theme_styles_t * styles;
static lv_theme_t theme; static lv_theme_t theme;
static disp_size_t disp_size; static disp_size_t disp_size;
static bool inited;
static lv_color_t color_scr; static lv_color_t color_scr;
static lv_color_t color_text; static lv_color_t color_text;
static lv_color_t color_card; static lv_color_t color_card;
@@ -647,7 +646,7 @@ lv_theme_t * lv_theme_default_init(lv_disp_t * disp, lv_color_t color_primary, l
/*This trick is required only to avoid the garbage collection of /*This trick is required only to avoid the garbage collection of
*styles' data if LVGL is used in a binding (e.g. Micropython) *styles' data if LVGL is used in a binding (e.g. Micropython)
*In a general case styles could be in simple `static lv_style_t my_style...` variables*/ *In a general case styles could be in simple `static lv_style_t my_style...` variables*/
if(!inited) { if(!lv_theme_default_is_inited()) {
LV_GC_ROOT(_lv_theme_default_styles) = lv_mem_alloc(sizeof(my_theme_styles_t)); LV_GC_ROOT(_lv_theme_default_styles) = lv_mem_alloc(sizeof(my_theme_styles_t));
styles = (my_theme_styles_t *)LV_GC_ROOT(_lv_theme_default_styles); styles = (my_theme_styles_t *)LV_GC_ROOT(_lv_theme_default_styles);
} }
@@ -667,8 +666,6 @@ lv_theme_t * lv_theme_default_init(lv_disp_t * disp, lv_color_t color_primary, l
style_init(); style_init();
inited = true;
if(disp == NULL || lv_disp_get_theme(disp) == &theme) lv_obj_report_style_change(NULL); if(disp == NULL || lv_disp_get_theme(disp) == &theme) lv_obj_report_style_change(NULL);
return (lv_theme_t *)&theme; return (lv_theme_t *)&theme;
@@ -676,14 +673,16 @@ lv_theme_t * lv_theme_default_init(lv_disp_t * disp, lv_color_t color_primary, l
lv_theme_t * lv_theme_default_get(void) lv_theme_t * lv_theme_default_get(void)
{ {
if(!inited) return NULL; if(!lv_theme_default_is_inited()) {
return NULL;
}
return (lv_theme_t *)&theme; return (lv_theme_t *)&theme;
} }
bool lv_theme_default_is_inited(void) bool lv_theme_default_is_inited(void)
{ {
return inited; return LV_GC_ROOT(_lv_theme_default_styles) == NULL ? false : true;
} }
@@ -1161,8 +1160,12 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj)
static void style_init_reset(lv_style_t * style) static void style_init_reset(lv_style_t * style)
{ {
if(inited) lv_style_reset(style); if(lv_theme_default_is_inited()) {
else lv_style_init(style); lv_style_reset(style);
}
else {
lv_style_init(style);
}
} }
#endif #endif

View File

@@ -64,7 +64,6 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj);
**********************/ **********************/
static my_theme_styles_t * styles; static my_theme_styles_t * styles;
static lv_theme_t theme; static lv_theme_t theme;
static bool inited;
/********************** /**********************
* MACROS * MACROS
@@ -164,13 +163,18 @@ static void style_init(bool dark_bg, const lv_font_t * font)
* GLOBAL FUNCTIONS * GLOBAL FUNCTIONS
**********************/ **********************/
bool lv_theme_mono_is_inited(void)
{
return LV_GC_ROOT(_lv_theme_default_styles) == NULL ? false : true;
}
lv_theme_t * lv_theme_mono_init(lv_disp_t * disp, bool dark_bg, const lv_font_t * font) lv_theme_t * lv_theme_mono_init(lv_disp_t * disp, bool dark_bg, const lv_font_t * font)
{ {
/*This trick is required only to avoid the garbage collection of /*This trick is required only to avoid the garbage collection of
*styles' data if LVGL is used in a binding (e.g. Micropython) *styles' data if LVGL is used in a binding (e.g. Micropython)
*In a general case styles could be in simple `static lv_style_t my_style...` variables*/ *In a general case styles could be in simple `static lv_style_t my_style...` variables*/
if(!inited) { if(!lv_theme_mono_is_inited()) {
LV_GC_ROOT(_lv_theme_default_styles) = lv_mem_alloc(sizeof(my_theme_styles_t)); LV_GC_ROOT(_lv_theme_default_styles) = lv_mem_alloc(sizeof(my_theme_styles_t));
styles = (my_theme_styles_t *)LV_GC_ROOT(_lv_theme_default_styles); styles = (my_theme_styles_t *)LV_GC_ROOT(_lv_theme_default_styles);
} }
@@ -183,8 +187,6 @@ lv_theme_t * lv_theme_mono_init(lv_disp_t * disp, bool dark_bg, const lv_font_t
style_init(dark_bg, font); style_init(dark_bg, font);
inited = true;
if(disp == NULL || lv_disp_get_theme(disp) == &theme) lv_obj_report_style_change(NULL); if(disp == NULL || lv_disp_get_theme(disp) == &theme) lv_obj_report_style_change(NULL);
return (lv_theme_t *)&theme; return (lv_theme_t *)&theme;
@@ -487,8 +489,12 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj)
static void style_init_reset(lv_style_t * style) static void style_init_reset(lv_style_t * style)
{ {
if(inited) lv_style_reset(style); if(lv_theme_mono_is_inited()) {
else lv_style_init(style); lv_style_reset(style);
}
else {
lv_style_init(style);
}
} }
#endif #endif

View File

@@ -38,6 +38,12 @@ extern "C" {
*/ */
lv_theme_t * lv_theme_mono_init(lv_disp_t * disp, bool dark_bg, const lv_font_t * font); lv_theme_t * lv_theme_mono_init(lv_disp_t * disp, bool dark_bg, const lv_font_t * font);
/**
* Check if the theme is initialized
* @return true if default theme is initialized, false otherwise
*/
bool lv_theme_mono_is_inited(void);
/********************** /**********************
* MACROS * MACROS
**********************/ **********************/