基于FreeTOS系统,LVGL多线程界面切换导致死机

界面只有一个按钮,点击按钮创建wifi测试线程,并向线程抛消息进行路由器连接操作,连接过程大致需要10秒。同时在点击按钮的时候也会给当前页面添加事件回调。具体代码流程如下:

//在连接路由器线程中连接成功之后会调用此函数,向当前界面抛出订阅事件
void wifi_conn_res_put(uint16_t *rssi_data)
{
    lv_event_send(fac_main, LV_EVENT_VALUE_CHANGED, rssi_data);
}

//当前界面注册的事件处理函数
static void wifi_test_handle(lv_event_t *e)
{
    int8_t *local_rssi = (int8_t*)lv_event_get_param(e);
    UI_FAC_LOGD("rssi:%d", *local_rssi);

    if(LV_EVENT_VALUE_CHANGED == lv_event_get_code(e)){
        lv_obj_del(fac_wifi_loading);
        fac_wifi_loading = NULL;
        fac_text_info.wifi_res = 1;         //测试成功设置为1
        fac_text_info.wifi_rssi = *local_rssi;
        setup_key_btn();     //绘制新的界面
    }
}
//此函数为wifi连接按钮的点击回调处理函数
static void btn_sw_event_cb(lv_event_t *e)
{
    lv_obj_t * l_btn = lv_event_get_target(e);
    lv_obj_set_style_bg_color(l_btn, lv_color_make(0x00, 0xFF, 0x00), LV_PART_MAIN);
    lv_obj_clear_flag(l_btn, LV_OBJ_FLAG_CLICKABLE);
    //为当前界面添加事件回调
    lv_obj_add_event_cb(fac_main, wifi_test_handle, LV_EVENT_VALUE_CHANGED, NULL);
    //显示loading图标
    fac_wifi_loading = lv_animimg_create(lv_scr_act());
    lv_obj_align(fac_wifi_loading, LV_ALIGN_LEFT_MID, 100, 0);
    creat_loading_icon(fac_wifi_loading);

    //启动wifi连接线程,并抛消息运行
   get_cloud_info_init();        //初始化路由器连接线程
   info_event_put(GC_MODUAL_FAC_WIFI_TEST);      //抛消息进行路由器连接
}

现在出现的问题是,在WiFi连接成功之后,在wifi_test_handle中能获取到rssi信息,但是会在此函数中高概率死机。具体死机信息如下:

event_send_core at /lvgl/src/core/lv_event.c:415
lv_event_send at /lvgl/src/core/lv_event.c:74
lv_refr_obj at /lvgl/src/core/lv_refr.c:711
 (inlined by) lv_refr_obj at /lvgl/src/core/lv_refr.c:689
lv_refr_obj at /lvgl/src/core/lv_refr.c:749
 (inlined by) lv_refr_obj at /lvgl/src/core/lv_refr.c:689
lv_refr_obj_and_children at /lvgl/src/core/lv_refr.c:647
lv_refr_area_part at /lvgl/src/core/lv_refr.c:579
layout_update_core at /lvgl/src/core/lv_obj_pos.c:1085
layout_update_core at /lvgl/src/core/lv_obj_pos.c:1077 (discriminator 3)
lv_refr_area at /lvgl/src/core/lv_refr.c:500
 (inlined by) lv_refr_areas at /lvgl/src/core/lv_refr.c:399
 (inlined by) _lv_disp_refr_timer at /lvgl/src/core/lv_refr.c:220
indev_pointer_proc at /lvgl/src/core/lv_indev.c:368
 (inlined by) lv_indev_read_timer_cb at /lvgl/src/core/lv_indev.c:100
lv_timer_exec at /lvgl/src/misc/lv_timer.c:313
 (inlined by) lv_timer_handler at /lvgl/src/misc/lv_timer.c:109
lv_task_handler at /lvgl/src/lv_api_map.h:37
 (inlined by) lv_main at /lvgl/lv_app.c:70

以上,麻烦各位老师帮忙看一下,多谢

对于那些报错信息,你可以打开 lv_conf.h 的 LV_USE_LOG 宏,并且设置 LV_LOG_LEVEL 为 LV_LOG_LEVEL_TRACE,之后再分析log。

请问老师我在wifi连接线程直接调用lv_event_send向界面发送事件,这时应该是在LVGL线程中处理吧?这种线程之间的处理方式是否如此实现?

wifi线程调用 lv_event_send 发送lvgl事件,lvgl线程在下一次执行 lv_task_handler() 进行处理。这是一个方法,是可以这样操作的。

您好,我也遇到同样的问题,我是用发生事件的方法还是死机,您是怎么解决的呢?

还是确保lvgl运行同一线程,使用工作项和列队,实现事件触发

尝试确保执行 lv_task_handler() 的时候不被抢占或者中断看看

我在使用过程中也出现了,主要原因是lvgl的线程是不安全的,解决就可以了,打印的logo不一定是那个位置的问题。

你好。我想问一下你是怎么解决这个问题的?加锁还是?

主要是分析LVGL是多线程刷新,需要打开等待对应操作的事件完成后,保证另一个线程执行完成了绘制或者创建对象后,再去做其它事情就可以了。

我也试过这种,就是在另一个线程中直接调用lv_event_send发送事件给ui线程,也是不行,不知道是什么问题

大佬,这种应该怎么实现它,谢谢你