mirror of
https://github.com/lvgl/lvgl.git
synced 2025-01-28 07:03:00 +08:00
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:
parent
e24a9fdf18
commit
6e00724797
@ -29,6 +29,23 @@
|
||||
/**********************
|
||||
* 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
|
||||
@ -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 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 uint32_t px_num;
|
||||
static lv_disp_t * disp_refr; /*Display being refreshed*/
|
||||
|
||||
#if LV_USE_PERF_MONITOR
|
||||
static uint32_t fps_sum_cnt;
|
||||
static uint32_t fps_sum_all;
|
||||
static perf_monitor_t perf_monitor;
|
||||
#endif
|
||||
|
||||
#if LV_USE_MEM_MONITOR
|
||||
static mem_monitor_t mem_monitor;
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
@ -71,7 +99,12 @@ static lv_disp_t * disp_refr; /*Display being refreshed*/
|
||||
*/
|
||||
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
|
||||
|
||||
#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) {
|
||||
perf_label = lv_label_create(lv_layer_sys());
|
||||
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);
|
||||
}
|
||||
|
||||
static uint32_t perf_last_time = 0;
|
||||
static uint32_t elaps_sum = 0;
|
||||
static uint32_t frame_cnt = 0;
|
||||
if(lv_tick_elaps(perf_last_time) < 300) {
|
||||
if(lv_tick_elaps(perf_monitor.perf_last_time) < 300) {
|
||||
if(px_num > 5000) {
|
||||
elaps_sum += elaps;
|
||||
frame_cnt ++;
|
||||
perf_monitor.elaps_sum += elaps;
|
||||
perf_monitor.frame_cnt ++;
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
if(elaps_sum == 0) elaps_sum = 1;
|
||||
if(frame_cnt == 0) fps = fps_limit;
|
||||
else fps = (1000 * frame_cnt) / elaps_sum;
|
||||
elaps_sum = 0;
|
||||
frame_cnt = 0;
|
||||
if(fps > fps_limit) fps = fps_limit;
|
||||
if(perf_monitor.elaps_sum == 0) {
|
||||
perf_monitor.elaps_sum = 1;
|
||||
}
|
||||
if(perf_monitor.frame_cnt == 0) {
|
||||
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;
|
||||
fps_sum_cnt ++;
|
||||
perf_monitor.fps_sum_all += fps;
|
||||
perf_monitor.fps_sum_cnt ++;
|
||||
uint32_t cpu = 100 - lv_timer_get_idle();
|
||||
lv_label_set_text_fmt(perf_label, "%"LV_PRIu32" FPS\n%"LV_PRIu32"%% CPU", fps, cpu);
|
||||
}
|
||||
#endif
|
||||
|
||||
#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) {
|
||||
mem_label = lv_label_create(lv_layer_sys());
|
||||
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);
|
||||
}
|
||||
|
||||
static uint32_t mem_last_time = 0;
|
||||
if(lv_tick_elaps(mem_last_time) > 300) {
|
||||
mem_last_time = lv_tick_get();
|
||||
if(lv_tick_elaps(mem_monitor.mem_last_time) > 300) {
|
||||
mem_monitor.mem_last_time = lv_tick_get();
|
||||
lv_mem_monitor_t mon;
|
||||
lv_mem_monitor(&mon);
|
||||
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
|
||||
void lv_refr_reset_fps_counter(void)
|
||||
{
|
||||
fps_sum_all = 0;
|
||||
fps_sum_cnt = 0;
|
||||
perf_monitor.fps_sum_all = 0;
|
||||
perf_monitor.fps_sum_cnt = 0;
|
||||
}
|
||||
|
||||
uint32_t lv_refr_get_fps_avg(void)
|
||||
{
|
||||
if(fps_sum_cnt == 0)
|
||||
if(perf_monitor.fps_sum_cnt == 0) {
|
||||
return 0;
|
||||
|
||||
return fps_sum_all / fps_sum_cnt;
|
||||
}
|
||||
return perf_monitor.fps_sum_all / perf_monitor.fps_sum_cnt;
|
||||
}
|
||||
#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);
|
||||
}
|
||||
|
||||
#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
|
||||
|
||||
|
@ -50,7 +50,6 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj);
|
||||
**********************/
|
||||
static my_theme_styles_t * styles;
|
||||
static lv_theme_t theme;
|
||||
static bool inited;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
@ -120,13 +119,18 @@ static void style_init(void)
|
||||
* 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)
|
||||
{
|
||||
|
||||
/*This trick is required only to avoid the garbage collection of
|
||||
*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*/
|
||||
if(!inited) {
|
||||
if(!lv_theme_basic_is_inited()) {
|
||||
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);
|
||||
}
|
||||
@ -139,9 +143,9 @@ lv_theme_t * lv_theme_basic_init(lv_disp_t * disp)
|
||||
|
||||
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;
|
||||
}
|
||||
@ -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)
|
||||
{
|
||||
if(inited) lv_style_reset(style);
|
||||
else lv_style_init(style);
|
||||
if(lv_theme_basic_is_inited()) {
|
||||
lv_style_reset(style);
|
||||
}
|
||||
else {
|
||||
lv_style_init(style);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -36,6 +36,12 @@ extern "C" {
|
||||
*/
|
||||
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
|
||||
**********************/
|
||||
|
@ -173,7 +173,6 @@ static void style_init_reset(lv_style_t * style);
|
||||
static my_theme_styles_t * styles;
|
||||
static lv_theme_t theme;
|
||||
static disp_size_t disp_size;
|
||||
static bool inited;
|
||||
static lv_color_t color_scr;
|
||||
static lv_color_t color_text;
|
||||
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
|
||||
*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*/
|
||||
if(!inited) {
|
||||
if(!lv_theme_default_is_inited()) {
|
||||
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);
|
||||
}
|
||||
@ -667,8 +666,6 @@ lv_theme_t * lv_theme_default_init(lv_disp_t * disp, lv_color_t color_primary, l
|
||||
|
||||
style_init();
|
||||
|
||||
inited = true;
|
||||
|
||||
if(disp == NULL || lv_disp_get_theme(disp) == &theme) lv_obj_report_style_change(NULL);
|
||||
|
||||
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)
|
||||
{
|
||||
if(!inited) return NULL;
|
||||
if(!lv_theme_default_is_inited()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (lv_theme_t *)&theme;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if(inited) lv_style_reset(style);
|
||||
else lv_style_init(style);
|
||||
if(lv_theme_default_is_inited()) {
|
||||
lv_style_reset(style);
|
||||
}
|
||||
else {
|
||||
lv_style_init(style);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -64,7 +64,6 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj);
|
||||
**********************/
|
||||
static my_theme_styles_t * styles;
|
||||
static lv_theme_t theme;
|
||||
static bool inited;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
@ -164,13 +163,18 @@ static void style_init(bool dark_bg, const lv_font_t * font)
|
||||
* 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)
|
||||
{
|
||||
|
||||
/*This trick is required only to avoid the garbage collection of
|
||||
*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*/
|
||||
if(!inited) {
|
||||
if(!lv_theme_mono_is_inited()) {
|
||||
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);
|
||||
}
|
||||
@ -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);
|
||||
|
||||
inited = true;
|
||||
|
||||
if(disp == NULL || lv_disp_get_theme(disp) == &theme) lv_obj_report_style_change(NULL);
|
||||
|
||||
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)
|
||||
{
|
||||
if(inited) lv_style_reset(style);
|
||||
else lv_style_init(style);
|
||||
if(lv_theme_mono_is_inited()) {
|
||||
lv_style_reset(style);
|
||||
}
|
||||
else {
|
||||
lv_style_init(style);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -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);
|
||||
|
||||
/**
|
||||
* Check if the theme is initialized
|
||||
* @return true if default theme is initialized, false otherwise
|
||||
*/
|
||||
bool lv_theme_mono_is_inited(void);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
Loading…
x
Reference in New Issue
Block a user