LVGL调试

前言

对于LVGL相关的任务,出现异常时会进入lv_assert_handler,为了准确定位是哪里出了问题,是出了什么问题导致的死机等,我们需要知道以下调试的方法

日志输出

默认情况下,LVGL的日志输出关闭,如果想要开启,在lv_conf.h中,将LV_USE_LOG配置为1

image-20250825203538913

自定义日志输出

自定义的日志回调函数通过注册回调函数的方式,将日志内容输出到串口、文件等。

1.设置LV_LOG_PRINTF = 0

image-20250825204040663

2.然后注册回调函数即可,之后LVGL内部所有通过 LV_LOG_INFOLV_LOG_WARNLV_LOG_ERRORLV_LOG_TRACE 等宏产生的日志,都会被发送到你注册的回调函数输出日志

image-20250825205330415

函数原型

1
void (*lv_log_print_g_cb_t)(lv_log_level_t level, const char * buf);

参数

  • level:表示输出日志的等级,有以下的等级

    • LV_LOG_LEVEL_TRACE 跟踪(最详细)
    • LV_LOG_LEVEL_INFO 信息
    • LV_LOG_LEVEL_WARN 警告
    • LV_LOG_LEVEL_ERROR 错误
    • LV_LOG_LEVEL_USER 用户自定义(如有)
  • buf:日志的实际文本

printf输出

1.设置LV_LOG_PRINTF = 1 ,开启通过 printf 输出日志的功能

image-20250825204040663

2.重定向printf输出到串口后,LVGL 日志会自动调用 printf() 函数输出到标准输出(通常是终端、串口、IDE 调试窗口等)。

输出日志到文件

动态内存监视

我们在使用lvgl的过程中,会分配指定大小的内存给LVGL的内存池,在运行过程中

会出现动态内存用完等情况,所以我们可以通过监视使用的内存大小变化来确定哪里占用了很多的内存,定位问题

使用lv_mem_monitor_t

LVGL 提供了函数来获取当前内存使用信息:

LVGL定义了一个结构体lv_mem_monitor_t,由于存储内存信息

1
2
3
4
5
6
7
8
typedef struct {
uint32_t total_size; // 堆总大小
uint32_t free_size; // 空闲内存
uint32_t used_cnt; // 已分配块数
uint32_t free_cnt; // 空闲块数
uint32_t largest_free_size; // 最大空闲块
uint8_t used_pct; // 已用百分比
} lv_mem_monitor_t;

获取内存信息

使用 lv_mem_monitor() 函数

1
2
3
4
5
6
7
8
9
10
11
void print_lvgl_mem_info(void)
{
lv_mem_monitor_t mon;
lv_mem_monitor(&mon);
printf("LVGL内存监视:\n");
printf(" 总容量: %u\n", mon.total_size);
printf(" 剩余: %u\n", mon.free_size);
printf(" 最大可用: %u\n", mon.largest_free_size);
printf(" 块数: 已用 %u, 空闲 %u\n", mon.used_cnt, mon.free_cnt);
printf(" 已用百分比: %u%%\n", mon.used_pct);
}

示例代码: 使用lvgl定时器回调,每秒输出内存占用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
void lv_mem_monitor_task(lv_timer_t * timer)
{
lv_mem_monitor_t mon;
lv_mem_monitor(&mon); // 填充 mon 结构体

SEGGER_RTT_printf(0,
"LVGL MEM: total=%lu Bytes, free=%lu Bytes, used=%u%%, max_used=%lu Bytes\n",
(unsigned long)mon.total_size,
(unsigned long)mon.free_size,
mon.used_pct,
(unsigned long)mon.max_used
);
}


void LvglHandlerTask(void *argument)
{
lv_timer_create(lv_mem_monitor_task, 1000, NULL); // 注册定时器每秒输出内存占用

while(1)
{
lv_task_handler(); // 启动lvgl的事务处理
osDelay(1);
}

}

我这里使用的是Jlink RTT输出,正常使用串口重定向printf或者串口输出都行!

使用LV_USE_MONITOR

image-20250829235640455