lvgl v9 手表项目, 存在多app 的时候,会出现切换 app 无法拉起显示页面的必现问题

手表项目, 用gui_app_fwk.c 提供的接口,搭建app 流程。

目前,有7个app 注册到该框架内,蓝牙功能已经打通。

测试必现的问题:

通过蓝牙通讯拉起其中一个测试 app, lv_async_call(test_opearation_from_ble_cb, vs) 将ble 接受的数据同步到该app. 等待5s, 退出当前app, 在拉起相关的第二个app,完成数据采集;再退出当前app, 拉起第三个app 展示数据分析的结果。 等待10s, 结束该app, 跳到主界面。

第一遍整个流程是可以正常的跑通,在主界面再次通过ble 发起测试app, 可以顺利拉起第一个app 的界面。5s后,当前界面没有显示,且第二个相关的界面没有被拉起来。整个流程就hold 住了。

采用的是拉起一个新的app 前, 就call gui_app_cleanup_now 清掉所有正在running 的app, 保持task 里最大在运行数目小于2的限制(增大到5, 现象依旧)。

如果不采用app 的形式, 当前界面上的控件,是无法改变显示的参数,维持创建时的参数。

麻烦分析一下这个问题,这个现象是必现的,且发生之后,端侧UI 会卡住,ble 功能正常。

为区分具体触发路径,请补充您使用的 SDK 版本,以及这几段代码或包含这几段代码的工程原文件:test_opearation_from_ble_cb、5 秒到期后的切换逻辑(含 gui_app_cleanup_now)、第一个 app 的启动/暂停/停止处理;若有卡住时的串口日志,也请一并贴出。

Sifli-sdk:v2.4.6 Lvgl: v9 v9.2.0

1.Ble:

case BLE_DATATRANS_COLLECT_DATA_VALUE:

    {

        // Store value that remote device writes

        uint32_t old_val = env->data.data;

        LOG_HEX("BLE RX", 16, para->value, para->len);

        // if (para->len <= 4)

        //     memcpy(&env->data.data, para->value, para->len);

        // LOG_I("Updated app value from:%d to:%d", old_val, env->data.data);

        // ble_app_start_send_thread();



        LOG_D("\_DATATRANS_COLLECT_DATA!!!");

      //  gui_app_cleanup();

        vsm_msg_t\* vsm = lv_malloc(sizeof(vsm_msg_t));

        vsm->type           = para->value\[1\];

        vsm->collect_type   = para->value\[0\];



        LOG_D("type:%d, collect:%d",para->value\[1\],  para->value\[0\]);



        bool ecg_active     = gui_app_is_actived("app_ecg");

        bool collect_active = gui_app_is_actived("app_collect");

       gui_runing_app_t\*  curRunningApp = gui_app_get_actived();

        LOG_D("cur app Id:%s", curRunningApp->id);

        if(vsm->type == 1)

        {

            gui_app_cleanup_now();

        }

       

        LOG_D("Active: ecg:%d, collect:%d",ecg_active, collect_active);



        if(!ecg_active && !collect_active)

        {

           LOG_D("APP ECG IS NOT ACTIVE JUMP ECG MAIN PAGE");

          //  gui_app_self_exit();

            gui_app_run("app_ecg");

         // \_ui_screen_change(&ui_ecg, LV_SCR_LOAD_ANIM_FADE_ON, 100, 0, &app_ecg_init);

            lv_async_call(ecg_opearation_from_ble_cb, vsm);

        }

        if(ecg_active)

        {

            LOG_D("ECG MAIN PAGE!");

            lv_async_call(ecg_opearation_from_ble_cb, vsm);

        }

        if(collect_active)

        {

            LOG_D("ECG COLLECT MAIN PAGE!");

            if( vsm->type == 0)

            {

                lv_async_call(collect_opearation_from_ble_cb, vsm);

            }else{

                LOG_D("JUMP ECG MAIN PAGE!");

                lv_async_call(ecg_opearation_from_ble_cb, vsm);

            }

        }

        lv_free(vsm);

        break;

    }

2.app:

app 1:

static void wait_collect_interval_timer(lv_timer_t *task)//延迟启动, 时长3s

{

// gui_app_cleanup_now();

 gui_app_run("app_collect");

// gui_app_exit(“app_ecg”);

 if (COMMON_APP_RET_OK != app_msg_send(APP_TASK_VSM, ecg_msg)) {

     LOG_D("Collect Data Msg:  app_msg_send() Fail");

 }

lv_timer_delete(collect_task);

}

extern void ecg_opearation_from_ble_cb(void *data)

{

LOG_D("ECG BLE CB!!!");

vsm_msg_t\* vsmOp = (vsm_msg_t\*)data ;

LOG_D(“User Op: Type: %d, Collect: %d”,vsmOp->type, vsmOp->collect_type);

//  \_ui_screen_change(&ui_collect, LV_SCR_LOAD_ANIM_FADE_ON, 100, 0, &ui_ecg_collect_init);

ecg_msg.main_task_type          = APP_TASK_VSM;

ecg_msg.u.vsm_msg.collect_type  = vsmOp->collect_type;

ecg_msg.u.vsm_msg.type          = vsmOp->type;

// gui_app_run(“app_ecg”);

collect_task = lv_timer_create(wait_collect_interval_timer, 3000, (void \*)0);

}

app2:

static void result_wait_time(lv_timer_t *task)//定时更新指针角度,刷新时钟显示,处理相关图像效果,记录时间状态

{

gui_app_cleanup_now();

gui_app_run("ecg_result");

// gui_app_exit(“app_collect”);

lv_timer_delete(result_task);

LOG_D("result_task Delete Timer!");

result_task = NULL;

// lv_screen_load_anim(ui_result, LV_SCR_LOAD_ANIM_NONE, 0, 0, true);

}

void collect_opearation_from_ble_cb(void *data)

{

LOG_D("Collect operation CB");

vsm_msg_t\* vsmOp = (vsm_msg_t\*)data ;



LOG_D("User Op: Type: %d, Collect: %d",vsmOp->type, vsmOp->collect_type);



common_app_msg_t  collect_msg;

collect_msg.main_task_type = APP_TASK_VSM;

collect_msg.u.vsm_msg.collect_type = vsmOp->collect_type;

collect_msg.u.vsm_msg.type = vsmOp->type;



if (COMMON_APP_RET_OK != app_msg_send(APP_TASK_VSM, collect_msg)) {

    LOG_D("Collect Data Msg:  app_msg_send() Fail");

}

// gui_app_run(“app_ecg”);

lv_timer_del(countdown_task);

countdown_task = NULL;

lv_label_set_text(coundown_time, "0");



result_task = lv_timer_create(result_wait_time, 3000, (void \*)0);

}

app3:

static void result_show_time(lv_timer_t *task)//定时更新指针角度,刷新时钟显示,处理相关图像效果,记录时间状态

{

// lv_obj_clean(ui_result);

lv_timer_delete(result_show_task);

LOG_D("result_show_task Delete Timer!");

result_show_task = NULL;

// lv_obj_add_flag(ui_result, LV_OBJ_FLAG_HIDDEN);

// gui_app_remove_page(“ecg_result”);

 gui_app_run("app_icons");

// gui_app_exit(“ecg_result”);

// lv_screen_load_anim(ui_ecg, LV_SCR_LOAD_ANIM_NONE, 100, 0, false);

}

页面是从BLE 发起的, 第一次ble 发起开始指令, 清掉所有running app, 拉起app1. 等3s, 清掉app1, 拉起app2. 在这个界面维持1min, ble 发起结束指令。等3s,清掉app 2, 拉起APP3. app3 目前是个假界面,仅显示。等3s ,清掉app3, 跳到app_icon(或其他界面)。 再从ble 发起开始指令,就会一直卡在app1.

uart:

[11:08:45.441]收←◆D/HEX BLE RX: 0000-0010: 01 01 ..
[2946477] D/ble_datatrans KE_EVT2: _DATATRANS_COLLECT_DATA!!!
[2946502] D/ble_datatrans KE_EVT2: type:1, collect:1
[2946523] D/ble_datatrans KE_EVT2: cur app Id:app_icons
[2946545] I/APP.FWK KE_EVT2: gui_app_cleanup_now Start
[2946568] D/APP.FWK KE_EVT2: send msg[GUI_APP_MSG_CLEANUP] [0x0] to gui_app_mbx tick:90045.
[2946603] D/APP.SCHE KE_EVT2: ----------------app_schedule_task---------------start
[2946634] I/APP.SCHE KE_EVT2: >>Execute msg[GUI_APP_MSG_CLEANUP] tick:90045
[2946662] D/APP.SCHE KE_EVT2: Stop all app
[2946684] D/APP.SCHE KE_EVT2: app_destory [app_icons]
[2946705] D/APP.SCHE KE_EVT2: page[app_icons][root] tgt_state [RESUMED] → [STOPED]
[2946737] D/APP.SCHE KE_EVT2: app[app_icons] tgt_state [RUNNING] → [DESTORYED]
[2946767] D/APP.SCHE KE_EVT2: app_destory [ecg_result]
[2946787] D/APP.SCHE KE_EVT2: page[ecg_result][root] tgt_state [PAUSED] → [STOPED]
[2946818] D/APP.SCHE KE_EVT2: app[ecg_result] tgt_state [RUNNING] → [DESTORYED]
[2946850] I/APP.SCHE KE_EVT2: page[app_icons][root] do ONPAUSE, 2005c124
[2946878] I/APP.SCHE KE_EVT2: page[ecg_result][root] do ONSTOP, 2004dc60
[2946906] D/[ECG_RESULT] KE_EVT2: ECG Result: Destory!
[2946948] D/APP.SCHE KE_EVT2: app[ecg_result] remove&free page[root] 2004dc60
[2946978] I/APP.SCHE KE_EVT2: app[ecg_result] do SUSPEND, 2004dd5c
[2947004] I/APP.SCHE KE_EVT2: page[app_icons][root] do ONSTOP, 2005c124
[2947082] D/APP.SCHE KE_EVT2: app[app_icons] remove&free page[root] 2005c124
[2947111] I/APP.SCHE KE_EVT2: app[app_icons] do SUSPEND, 2006b068
[2947136] I/APP.SCHE KE_EVT2: app[app_icons] do DESTROY, 2006b068
[2947162] I/APP.SCHE KE_EVT2: app[ecg_result] do DESTROY, 2004dd5c
[2947187] D/APP.SCHE KE_EVT2: app_schedule_task done.
[2947207] I/APP.FWK KE_EVT2: gui_app_cleanup_now Cnt 2
[2947228] I/APP.FWK KE_EVT2: gui_app_cleanup_now Done.
[2947249] D/ble_datatrans KE_EVT2: Active: ecg:0, collect:0
[2947271] D/ble_datatrans KE_EVT2: APP ECG IS NOT ACTIVE JUMP ECG MAIN PAGE
[2947301] D/APP.FWK KE_EVT2: send msg[GUI_APP_MSG_RUN_APP] [app_ecg] to gui_app_mbx tick:90067.
[2947338] I/APP.FWK.INT KE_EVT2: [app_ecg]
[2947355] I/APP.FWK KE_EVT2: gui_app_run: id:app_ecg, err:0
[2947384] D/[UI_ECG] watch: ECG BLE CB!!!
[2947400] D/[UI_ECG] watch: User Op: Type: 1, Collect: 1
[2947745] D/APP.SCHE watch: ----------------app_schedule_task---------------start
[2947777] I/APP.SCHE watch: >>Execute msg[GUI_APP_MSG_RUN_APP] tick:90067
[2947806] I/APP.SCHE watch: app[app_ecg] do LOAD, 2004dd5c
[2947829] I/APP.FWK watch: finding app_ecg in builtin apps…
[2947853] D/APP.SCHE watch: app[app_ecg] tgt_state [LAUNCHED] → [RUNNING]
[2947882] I/APP.SCHE watch: app[app_ecg] do START, 2004dd5c
[2947905] I/APP.FWK.INT watch: [app_ecg]
[2947922] D/APP.FWK watch: send msg[GUI_APP_MSG_OPEN_PAGE] [0x2004dd5c] to gui_app_mbx tick:90086.
[2947959] D/APP.SCHE watch: running apps idx[0]:[app_ecg].
[2947982] D/APP.SCHE watch: running apps idx[0]:[app_ecg].
[2948004] I/APP.SCHE watch: >>Execute msg[GUI_APP_MSG_OPEN_PAGE] tick:90086
[2948035] D/APP.SCHE watch: app[app_ecg] create page[root] 2005b82c
[2948062] D/APP.SCHE watch: page[app_ecg][root] tgt_state [CREATED] → [RESUMED]
[2948094] D/APP.SCHE watch: Pause all app, and resume to app_ecg app
[2948121] D/APP.SCHE watch: running apps idx[0]:[app_ecg].
[2948156] I/APP.SCHE watch: page[app_ecg][root] do ONSTART, 2005b82c
[2948184] D/[UI_ECG] watch: ECG Create!
ui_titlegroup_create
ui_titlegroup_create title
ui_titlegroup_create subtitle
ui_titlegroup_create finish
[2948528] D/APP.SCHE watch: running apps idx[0]:[app_ecg].
[2948553] D/APP.SCHE watch: running apps idx[0]:[app_ecg].
[2948578] I/APP.SCHE watch: page[app_ecg][root] do ONRESUME, 2005b82c
[2948605] D/[UI_ECG] watch: ECG : Resume!
[2948622] I/APP.SCHE watch: Try setup trans-anim
[2948641] I/APP.SCHE watch: Trans-anim is OFF, skip.
[2948663] D/APP.SCHE watch: running apps idx[0]:[app_ecg].
[2948685] D/APP.SCHE watch: running apps idx[0]:[app_ecg].
[2948708] D/APP.SCHE watch: running apps idx[0]:[app_ecg].
[2948731] D/APP.SCHE watch: app_schedule_task done.

[11:08:48.468]收←◆[3045610] D/APP.FWK watch: send msg[GUI_APP_MSG_RUN_APP] [app_collect] to gui_app_mbx tick:93073.
[3045651] I/APP.FWK.INT watch: [app_collect]
[3045669] I/APP.FWK watch: gui_app_run: id:app_collect, err:0

[11:08:48.495]收←◆[3046491] D/APP.SCHE watch: ----------------app_schedule_task---------------start
[3046521] I/APP.SCHE watch: >>Execute msg[GUI_APP_MSG_RUN_APP] tick:93073
[3046552] I/APP.SCHE watch: app[app_collect] do LOAD, 20072858
[3046576] I/APP.FWK watch: finding app_collect in builtin apps…
[3046602] D/APP.SCHE watch: app[app_collect] tgt_state [LAUNCHED] → [RUNNING]
[3046632] I/APP.SCHE watch: app[app_collect] do START, 20072858
[3046659] I/APP.FWK.INT watch: [app_collect]
[3046679] D/APP.FWK watch: send msg[GUI_APP_MSG_OPEN_PAGE] [0x20072858] to gui_app_mbx tick:93105.
[3046716] D/APP.SCHE watch: running apps idx[0]:[app_collect].
[3046740] D/APP.SCHE watch: running apps idx[1]:[app_ecg].
[3046762] D/APP.SCHE watch: running apps idx[0]:[app_ecg].
[3046785] D/APP.SCHE watch: running apps idx[1]:[app_collect].
[3046808] I/APP.SCHE watch: >>Execute msg[GUI_APP_MSG_OPEN_PAGE] tick:93105
[3046839] D/APP.SCHE watch: app[app_collect] create page[root] 2006e504
[3046866] D/APP.SCHE watch: page[app_collect][root] tgt_state [CREATED] → [RESUMED]
[3046898] D/APP.SCHE watch: Pause all app, and resume to app_collect app
[3046925] D/APP.SCHE watch: page[app_ecg][root] tgt_state [RESUMED] → [PAUSED]
[3046955] D/APP.SCHE watch: running apps idx[0]:[app_ecg].
[3046977] D/APP.SCHE watch: running apps idx[1]:[app_collect].
[3047002] I/APP.SCHE watch: page[app_ecg][root] do ONPAUSE, 2005b82c
[3047028] D/[UI_ECG] watch: ECG: Pause!
[3047067] I/APP.SCHE watch: page[app_collect][root] do ONSTART, 2006e504
[3047095] D/[UI_COLLECT] watch: ECG COLLECT: Create!
[3047115] D/[UI_COLLECT] watch: ui_ecg_collect_init
[3047421] D/APP.SCHE watch: running apps idx[0]:[app_ecg].
[3047446] D/APP.SCHE watch: running apps idx[1]:[app_collect].
[3047470] D/APP.SCHE watch: running apps idx[0]:[app_ecg].
[3047492] D/APP.SCHE watch: running apps idx[1]:[app_collect].
[3047518] I/APP.SCHE watch: page[app_collect][root] do ONRESUME, 2006e504
[3047547] D/[UI_COLLECT] watch: COLLECT : Resume!
[3047586] D/[UI_COLLECT] watch: COLLECT TIMER START
[3047607] I/APP.SCHE watch: Try setup trans-anim
app_anim_buf_alloc: 0x603252f0 index 0 size 351000
[3047661] I/APP.ANI watch: buf = 603252f0
[3048053] I/APP.ANI watch: app_trans_animation_obj_create = 2005c124
app_anim_buf_alloc: 0x602cf7d8 index 1 size 351000
[3048103] I/APP.ANI watch: buf = 602cf7d8

[11:08:48.625]收←◆assertion “z != ((void *)0)” failed: file “D:\OpenSiFli\sifli-sdk\external\lvgl_v9\src\libs\tiny_ttf\stb_truetype_htcw.h”, line 3160, function: stbtt__new_active
thread:watch abort!

[11:09:45.548]收←◆D/HEX BLE RX: 0000-0010: 01 00 ..
[4916104] D/ble_datatrans KE_EVT2: _DATATRANS_COLLECT_DATA!!!
[4916129] D/ble_datatrans KE_EVT2: type:0, collect:1
[4916151] D/ble_datatrans KE_EVT2: cur app Id:app_collect
[4916172] D/ble_datatrans KE_EVT2: Active: ecg:0, collect:1
[4916195] D/ble_datatrans KE_EVT2: ECG COLLECT MAIN PAGE!

[11:08:48.625]收←◆assertion “z != ((void *)0)” failed: file “D:\OpenSiFli\sifli-sdk\external\lvgl_v9\src\libs\tiny_ttf\stb_truetype_htcw.h”, line 3160, function: stbtt__new_active
thread:watch abort!

这个abort 不是必现,整个流程是一样的。 这个abort 有处理的方法没有吗?

上面的日志对应ble 发起结束到第二次发起开始的阶段,对应问题出现的位置

收到以上信息,为进一步区分问题,还请您提供:
① app_collect的字体创建/销毁及 ONSTART/ONPAUSE/ONSTOP 代码;② 编译生成的内存与线程配置(LV_USE_STDLIB_MALLOC、LV_MEM_SIZE、LV_USE_OS)及实际 app_anim_buf_alloc()实现;③ 一次未出现abort、但仍然卡住时的最后日志和watch线程调用栈。

  1. app_collectvoid ui_ecg_chart_canvas(void)

{

   ui_chart_group = lv_obj_create(ui_collect);

   lv_obj_set_size(ui_chart_group, 380, 240);          // 尺寸同图片

   lv_obj_set_x(ui_chart_group, -30);

   lv_obj_set_y(ui_chart_group, 15);

  // lv_obj_set_align(ui_chart_group, LV_ALIGN_CENTER);

   lv_obj_set_style_radius(ui_chart_group, 40, 0);     // 圆角半径

   lv_obj_set_style_clip_corner(ui_chart_group, true, 0); // 开启圆角裁剪

// lv_obj_set_style_bg_color(ui_chart_group, LV_COLOR_BLACK, LV_PART_MAIN);

// // lv_obj_set_style_bg_opa(ui_chart_group, LV_OPA_TRANSP, 0); // 背景透明(可选)

// // lv_obj_set_pad_all(ecg_bg_img, 0); // 去除内边距

// // lv_obj_set_style_pad_left(ecg_bg_img, 0, 0);

   lv_obj_set_style_border_width(ui_chart_group, 0, LV_PART_MAIN | LV_STATE_DEFAULT); // 去除边框

   lv_obj_remove_flag(ui_chart_group, LV_OBJ_FLAG_SCROLLABLE);

   lv_obj_set_style_pad_left(ui_chart_group, 50, 0);



   ui_chart_ecg = lv_chart_create(ui_chart_group);

   lv_obj_set_width(ui_chart_ecg, 420);

   lv_obj_set_height(ui_chart_ecg, 250);

   lv_obj_set_x(ui_chart_ecg, -70);

   lv_obj_set_y(ui_chart_ecg, -42);

   lv_obj_remove_flag(ui_chart_ecg, LV_OBJ_FLAG_SCROLLABLE);      /// Flags

   lv_chart_set_type(ui_chart_ecg, LV_CHART_TYPE_LINE);



   lv_chart_set_point_count(ui_chart_ecg, CHART_POINTS);

   lv_chart_set_update_mode(ui_chart_ecg, LV_CHART_UPDATE_MODE_SHIFT);

   lv_chart_set_div_line_count(ui_chart_ecg, 2, 0);

   lv_obj_set_style_line_width(ui_chart_ecg, 1, LV_PART_ITEMS);

   lv_obj_set_style_size(ui_chart_ecg, 0, 0, LV_PART_INDICATOR);




       /\* 波形序列 — 绿色 \*/

   ui_chart_ecg_series = lv_chart_add_series(ui_chart_ecg,

       lv_palette_main(LV_PALETTE_RED), LV_CHART_AXIS_PRIMARY_Y);



   /\* 预填充基线 \*/

   for (int i = 0; i < CHART_POINTS; i++) {

       lv_chart_set_next_value(ui_chart_ecg, ui_chart_ecg_series, 0);

   }



   /\* 设置 Y 轴范围 \*/

   lv_chart_set_range(ui_chart_ecg, LV_CHART_AXIS_PRIMARY_Y, MIN_VALUE, MAX_VALUE);

}

static void on_start(void) {

   LOG_D("ECG COLLECT: Create!");



   

   LOG_D("ui_ecg_collect_init");

   collect_font = font_DroidSans_converter(28);



   ui_collect = lv_obj_create(lv_scr_act());

   lv_obj_set_size(ui_collect, LV_HOR_RES_MAX, LV_VER_RES_MAX);

   lv_obj_set_style_bg_color(ui_collect, LV_COLOR_BLACK, LV_PART_MAIN);

   // lv_obj_add_flag(ui_collect, LV_OBJ_FLAG_HIDDEN);

   lv_obj_clear_flag(ui_collect, LV_OBJ_FLAG_SCROLLABLE);

   lv_obj_align(ui_collect, LV_ALIGN_CENTER, 0, 0);

   lv_obj_set_style_border_width(ui_collect, 0, LV_PART_MAIN | LV_STATE_DEFAULT);



   ui_ecg_chart_canvas();



   // CountDown Part

   ecg_countdown = ui_count_down_create(ui_collect);

   lv_obj_set_x(ecg_countdown, -70);

   lv_obj_set_y(ecg_countdown, -65);

   lv_obj_set_align(ecg_countdown, LV_ALIGN_BOTTOM_LEFT);

   lv_obj_set_style_border_width(ecg_countdown, 0, LV_PART_MAIN | LV_STATE_DEFAULT);

   lv_obj_set_style_border_color(ecg_countdown, lv_color_hex(0x545454), LV_PART_MAIN | LV_STATE_DEFAULT);

   lv_obj_set_style_border_opa(ecg_countdown, 255, LV_PART_MAIN | LV_STATE_DEFAULT);

   lv_obj_set_style_border_side(ecg_countdown, LV_BORDER_SIDE_BOTTOM, LV_PART_MAIN | LV_STATE_DEFAULT);



   coundown_time = ui_comp_get_child(ecg_countdown, UI_COMP_TITLEGROUP_TITLE);

   lv_label_set_text(coundown_time, "60");



   coundown_unit = ui_comp_get_child(ecg_countdown, UI_COMP_TITLEGROUP_SUBTITLE);

   lv_obj_set_style_text_font(coundown_unit, collect_font, LV_PART_MAIN | LV_STATE_DEFAULT);



   // Inform

   ecg_inform =  lv_label_create(ui_collect);

   lv_obj_set_width(ecg_inform, 360);

   lv_obj_set_height(ecg_inform, 60);

   lv_obj_set_align(ecg_inform, LV_ALIGN_BOTTOM_MID);

   lv_obj_set_x(ecg_inform, 0);

   lv_obj_set_y(ecg_inform, 10);    // ui_ecg_label = lv_label_create(ui_ecg);

  // lv_label_set_text(ecg_inform, user_notification\[2\]);

   lv_label_set_text(ecg_inform, user_notification\[1\]);

   lv_obj_set_style_text_color(ecg_inform, lv_color_hex(0xffffff), LV_PART_MAIN | LV_STATE_DEFAULT);

   lv_obj_set_style_text_opa(ecg_inform, 255, LV_PART_MAIN | LV_STATE_DEFAULT);

   lv_obj_set_style_text_font(ecg_inform, collect_font, LV_PART_MAIN | LV_STATE_DEFAULT);

   lv_obj_set_style_text_align(ecg_inform, LV_TEXT_ALIGN_LEFT, LV_PART_MAIN | LV_STATE_DEFAULT);

   lv_label_set_long_mode(ecg_inform, LV_LABEL_LONG_SCROLL_CIRCULAR);

   lv_obj_set_flex_grow(ecg_inform, 1);

   lv_obj_set_style_pad_left(ecg_inform, 20, 0);



   // countdown_task = lv_timer_create(countdown_time_redraw, 1000, (void \*)0);

};

void ecg_collect_init(void)

{

   on_start();

}

static void on_resume(void) {

   LOG_D("COLLECT : Resume!");



   lv_obj_del(ui_ecg);

   if (NULL == countdown_task)

   {

     //  gui_app_remove_page("app_ecg");

       curCount = COUNT_START;

       countdown_task = lv_timer_create(countdown_time_redraw, 1000, (void \*)0);

       LOG_D("COLLECT TIMER START");

   }



  // gui_app_remove_page("app_ecg");



  // gui_app_exit("app_ecg");

};

static void on_pause(void) {

   LOG_D("COLLECT: Pause!");

};

static void on_stop(void) {

   LOG_D("COLLECT: Destroy!");



   if(ui_collect) lv_obj_del(ui_collect);



   ui_collect          = NULL;

   ui_chart_group      = NULL;

   ecg_countdown       = NULL;

   ecg_inform          = NULL;

   collect_font        = NULL;

   countdown_task      = NULL;

   coundown_time       = NULL;

   coundown_unit       = NULL;

};

字体:

extern const unsigned char DroidSansFallback[];

extern const int DroidSansFallback_size;

static lv_font_t *chinese_font = NULL;

lv_font_t* font_DroidSans_converter(int32_t font_size)

{

   chinese_font = lv_tiny_ttf_create_data(DroidSansFallback, DroidSansFallback_size, font_size);

   return chinese_font;

}
2. lv_conf.h 只是复制了template.h 里面的配置没动 , 实际 app_anim_buf_alloc() 这个不是自己实现的。 动画这块目前还没到考虑阶段, 也没配置任何anim 的参数。 动画这块应该是贵司接口处理的。
3. 无 abort:
[2857583] I/APP.FWK KE_EVT2: gui_app_run: id:app_ecg, err:0
[2857612] D/[UI_ECG] watch: ECG BLE CB!!!
[2857628] D/[UI_ECG] watch: User Op: Type: 1, Collect: 1

[14:30:29.281]收←◆[2858614] D/APP.SCHE watch: ----------------app_schedule_task---------------start
[2858647] I/APP.SCHE watch: >>Execute msg[GUI_APP_MSG_RUN_APP] tick:87342
[2858677] I/APP.SCHE watch: app[app_ecg] do LOAD, 2004dd5c
[2858700] I/APP.FWK watch: finding app_ecg in builtin apps…
[2858727] D/APP.SCHE watch: app[app_ecg] tgt_state [LAUNCHED] → [RUNNING]
[2858756] I/APP.SCHE watch: app[app_ecg] do START, 2004dd5c
[2858779] I/APP.FWK.INT watch: [app_ecg]
[2858797] D/APP.FWK watch: send msg[GUI_APP_MSG_OPEN_PAGE] [0x2004dd5c] to gui_app_mbx tick:87381.
[2858834] D/APP.SCHE watch: running apps idx[0]:[app_ecg].
[2858856] D/APP.SCHE watch: running apps idx[0]:[app_ecg].
[2858879] I/APP.SCHE watch: >>Execute msg[GUI_APP_MSG_OPEN_PAGE] tick:87381
[2858908] D/APP.SCHE watch: app[app_ecg] create page[root] 2004e950
[2858934] D/APP.SCHE watch: page[app_ecg][root] tgt_state [CREATED] → [RESUMED]
[2858965] D/APP.SCHE watch: Pause all app, and resume to app_ecg app
[2858992] D/APP.SCHE watch: running apps idx[0]:[app_ecg].
[2859028] I/APP.SCHE watch: page[app_ecg][root] do ONSTART, 2004e950
[2859056] D/[UI_ECG] watch: ECG Create!
ui_titlegroup_create
ui_titlegroup_create title
ui_titlegroup_create subtitle
ui_titlegroup_create finish
[2859382] D/APP.SCHE watch: running apps idx[0]:[app_ecg].
[2859407] D/APP.SCHE watch: running apps idx[0]:[app_ecg].
[2859431] I/APP.SCHE watch: page[app_ecg][root] do ONRESUME, 2004e950
[2859458] D/[UI_ECG] watch: ECG : Resume!
[2859475] I/APP.SCHE watch: Try setup trans-anim
[2859494] I/APP.SCHE watch: Trans-anim is OFF, skip.
[2859514] D/APP.SCHE watch: running apps idx[0]:[app_ecg].
[2859536] D/APP.SCHE watch: running apps idx[0]:[app_ecg].
[2859558] D/APP.SCHE watch: running apps idx[0]:[app_ecg].
[2859581] D/APP.SCHE watch: app_schedule_task done.

[14:30:32.248]收←◆[2955817] D/APP.FWK watch: send msg[GUI_APP_MSG_RUN_APP] [app_collect] to gui_app_mbx tick:90348.
[2955858] I/APP.FWK.INT watch: [app_collect]
[2955875] I/APP.FWK watch: gui_app_run: id:app_collect, err:0

[14:30:32.295]收←◆[2957351] D/APP.SCHE watch: ----------------app_schedule_task---------------start
[2957382] I/APP.SCHE watch: >>Execute msg[GUI_APP_MSG_RUN_APP] tick:90348
[2957413] I/APP.SCHE watch: app[app_collect] do LOAD, 20072938
[2957437] I/APP.FWK watch: finding app_collect in builtin apps…
[2957463] D/APP.SCHE watch: app[app_collect] tgt_state [LAUNCHED] → [RUNNING]
[2957494] I/APP.SCHE watch: app[app_collect] do START, 20072938
[2957520] I/APP.FWK.INT watch: [app_collect]
[2957541] D/APP.FWK watch: send msg[GUI_APP_MSG_OPEN_PAGE] [0x20072938] to gui_app_mbx tick:90400.
[2957578] D/APP.SCHE watch: running apps idx[0]:[app_collect].
[2957602] D/APP.SCHE watch: running apps idx[1]:[app_ecg].
[2957624] D/APP.SCHE watch: running apps idx[0]:[app_ecg].
[2957647] D/APP.SCHE watch: running apps idx[1]:[app_collect].
[2957670] I/APP.SCHE watch: >>Execute msg[GUI_APP_MSG_OPEN_PAGE] tick:90400
[2957701] D/APP.SCHE watch: app[app_collect] create page[root] 2006e5e4
[2957728] D/APP.SCHE watch: page[app_collect][root] tgt_state [CREATED] → [RESUMED]
[2957760] D/APP.SCHE watch: Pause all app, and resume to app_collect app
[2957788] D/APP.SCHE watch: page[app_ecg][root] tgt_state [RESUMED] → [PAUSED]
[2957818] D/APP.SCHE watch: running apps idx[0]:[app_ecg].
[2957840] D/APP.SCHE watch: running apps idx[1]:[app_collect].
[2957864] I/APP.SCHE watch: page[app_ecg][root] do ONPAUSE, 2004e950
[2957891] D/[UI_ECG] watch: ECG: Pause!
[2957929] I/APP.SCHE watch: page[app_collect][root] do ONSTART, 2006e5e4
[2957958] D/[UI_COLLECT] watch: ECG COLLECT: Create!
[2957978] D/[UI_COLLECT] watch: ui_ecg_collect_init
[2958284] D/APP.SCHE watch: running apps idx[0]:[app_ecg].
[2958309] D/APP.SCHE watch: running apps idx[1]:[app_collect].
[2958334] D/APP.SCHE watch: running apps idx[0]:[app_ecg].
[2958356] D/APP.SCHE watch: running apps idx[1]:[app_collect].
[2958382] I/APP.SCHE watch: page[app_collect][root] do ONRESUME, 2006e5e4
[2958411] D/[UI_COLLECT] watch: COLLECT : Resume!
[2958433] D/[UI_COLLECT] watch: COLLECT TIMER START
[2958453] I/APP.SCHE watch: Try setup trans-anim
app_anim_buf_alloc: 0x603252f0 index 0 size 351000
[2958503] I/APP.ANI watch: buf = 603252f0

收到以上信息。结合补充的代码和日志,目前建议先核对并修正以下内容

1. 字体创建与释放需要配对。

采集页每次启动都会执行:

collect_font = font_DroidSans_converter(28);

该函数内部每次调用lv_tiny_ttf_create_data()创建新字体,但目前提供的退出代码只有:

collect_font = NULL;

将指针置空不会释放字体及其缓存,删除页面控件也不会自动释放字体。如果工程其他位置没有对应的销毁处理,重复进入页面会留下未释放的字体资源。

对于采集页独占的字体,应在删除使用该字体的控件、确认没有其他使用者后,调用:

lv_tiny_ttf_destroy(collect_font);
collect_font = NULL;

如果工程已有统一的字体管理和释放机制,请以实际所有权为准,避免重复释放。日志中已经出现字体临时分配失败,因此这一项优先核对。

2. 异步参数不能在回调使用结束前释放。

目前 BLE 处理中的代码是:

lv_async_call(ecg_opearation_from_ble_cb, vsm);
lv_free(vsm);

lv_async_call() 保存的是vsm指针,不会复制其指向的数据。异步回调可能尚未读取数据,发送方就已经释放了这块内存。

当前 lv_async_call() 后立即执行 lv_free(vsm),不能保证回调读取时数据仍然有效。建议成功提交后由回调在使用结束时释放;提交失败时由调用方释放。

3. 同步清理应用的接口需要在GUI线程( watch)执行。

目前 BLE 处理代码直接调用:

gui_app_cleanup_now();

gui_app_cleanup_now() 需要在 GUI 线程执行,本项目的 GUI 线程是watch。目前代码从 BLE 的KE_EVT2线程直接调用了该接口,需要调整为由 BLE 通知watch,再由watch执行清理,清理完成后再启动目标应用。

建议先完成上述三项的核对和修改。 如果仍出现字体断言,请再补充分配失败时的内存状态;如果仍是无断言卡住,则获取watch线程的完整调用栈,再针对具体位置继续排查。