LVGL v9 watch project: Switching apps fails to bring up the display page when multiple apps exist — reproducible issue

Smartwatch project: build the app flow using the interfaces provided by gui_app_fwk.c.

Currently, 7 apps are registered in this framework, and Bluetooth functionality is already working.

Issue that always reproduces in testing:

When launching one of the test apps via Bluetooth communication, lv_async_call(test_opearation_from_ble_cb, vs) syncs the BLE-received data to that app. Wait 5s, exit the current app, then launch the related second app to complete data collection; then exit the current app, launch the third app to display the data analysis results. Wait 10s, end that app, and jump to the main screen.

The first time, the whole flow runs normally. From the main screen, when the test app is started again via BLE, the first app’s screen appears smoothly. After 5s, the current screen is no longer displayed, and the second related screen is not launched. The entire flow then hangs.

The approach used is to call gui_app_cleanup_now before launching a new app to clear all currently running apps, keeping the maximum number of running tasks below 2 (even after increasing to 5, the phenomenon remains).

If the app approach is not used, the controls on the current screen are unable to change the displayed parameters; they remain at the values set during creation.

Please analyze this issue. The phenomenon is always reproducible, and after it occurs, the device-side UI freezes while BLE functionality remains normal.

为区分具体触发路径,请补充您使用的 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 发起结束到第二次发起开始的阶段,对应问题出现的位置

Received the above information. To further distinguish the issue, please provide: ① the font creation/destruction and ONSTART/ONPAUSE/ONSTOP code for app_collect; ② the compile-time memory and thread configuration (LV_USE_STDLIB_MALLOC, LV_MEM_SIZE, LV_USE_OS) and the actual app_anim_buf_alloc() implementation; ③ the last logs and the watch thread call stack from a case where no abort occurred but it still hung.

  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

Received the above information. Based on the supplementary code and logs, it is currently recommended to first verify and correct the following items:

1. Font creation and release must be paired.

Every time the collection page starts, the following is executed:

collect_font = font_DroidSans_converter(28);

This function internally calls lv_tiny_ttf_create_data() each time to create a new font, but the exit code currently provided only does:

collect_font = NULL;

Simply setting the pointer to NULL does not release the font or its cache, and deleting page controls does not automatically release the font either. If no corresponding destruction is handled elsewhere in the project, repeatedly entering the page will leave unreleased font resources.

For a font exclusively used by the collection page, after deleting the controls that use the font and confirming there are no other users, you should call:

lv_tiny_ttf_destroy(collect_font);
collect_font = NULL;

If the project already has a unified font management and release mechanism, follow the actual ownership to avoid double release. The logs already show temporary font allocation failures, so this item should be checked first.

2. Asynchronous parameters must not be released before the callback has finished using them.

Currently, the code in the BLE handling is:

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

lv_async_call() saves the vsm pointer, not a copy of the data it points to. The asynchronous callback may not have read the data yet when the sender has already freed this memory.

Currently, lv_free(vsm) is executed immediately after lv_async_call(), which does not guarantee that the data is still valid when the callback reads it. It is recommended that, upon successful submission, the callback releases the memory after use; on submission failure, the caller should release it.

3. The interface for synchronous cleanup of the application must be executed on the GUI thread (watch).

Currently, the BLE handling code directly calls:

gui_app_cleanup_now();

gui_app_cleanup_now() needs to be executed on the GUI thread, which in this project is watch. Currently, the code calls this interface directly from the BLE KE_EVT2 thread. It needs to be adjusted so that BLE notifies watch, and then watch performs the cleanup, after which the target application is started.

It is recommended to complete the verification and modifications of the above three items first. If font assertions still occur, please further supplement the memory state during allocation failure; if it still gets stuck without assertions, obtain the complete call stack of the watch thread and continue investigating the specific location.