LVGL内存优化

裁剪LVGL

LVGL主打的就是轻量且多功能,其官网介绍中有这两句话:

  • RAM: 4kB + 150byte / widget (~48kB for a UI with a few screens)
  • Flash:~1OOkB for LVGL (depends on the enabled features)

这里的意思是,经过裁剪之后能达到这样的效果,并不是我们拿到手默认的配置就能达到这样效果。
LVGL的裁剪在lv_conf.h文件中进行。

实际项目过程中,我们的Flash和SRAM可能不够用,所以需要进行裁剪优化LVGL占用的内存!

Flash优化

lvgl的flash占用主要是以下内容:

  • 控件与核心代码(lv_conf.h中控制,使能的控件越多,占用越多)

  • 字体点阵数组(如ui_font_opensasnsitalic100.o里的点阵数据)。

  • 图片/图标等资源(如你用LVGL/SquareLine导出的图片c文件)。

  • 音频、logo、动画帧等。

这些都是由const修饰的数组,只读区域在Flash之中

字体裁剪

在使用SquareLine导出字体库的时候,默认会导出所有的标准ASCII字符,此时如果字体很大(size是100扽等等), 且我们使用了数字0~9的时候,一定要记得只导出使用的数字的字体,否则就会非常非常大!!

以下减小字体占用Flash体积的方法,适用于所有字体,建议每次都这样做!

就比如这里我使用了一个size为100的字体,我只想使用0~9数字,就是我指定的Symbols字符

但是这里的Range: 0x20-0x7f 表示从 Unicode 0x20(空格)到 0x7f(DEL),即包含了所有标准ASCII字符会一起导出。

最终导出的文件有20000多行,占用了160KB的flash

image-20250824170232981

把Range删掉后,这样就只会导出Symbols中的字符0~9,代码也只剩2000行,同时Flash占用也只有10多KB

image-20250824170449838

当然除了使用SquareLine生成,也可以使用lvgl官网提供的字体转换器得到字体的.c文件,就只会转换你想要的字符:

字体转换器 — LVGL

lv_conf.h

字体

这里是LVGL自带的一些字体,保证不报错即可,因为我们都是使用自定义字体

image-20250824173308280

控件

不使用的控件不启用,节省资源

image-20250824173517266

SRAM优化

lvgl的SRAM占用主要有以下内容:

1.动态分配内存

  • LVGL内存池(如lv_mem_core_builtin.o,ZI Data 49152字节)。

  • FreeRTOS堆(如heap_4.o,ZI Data 15360字节)。

  • malloc/new等动态分配的内存。

2.LVGL显示缓冲区

  • 如 lv_port_disp.o 的 ZI Data(显示buffer),例如 ZI Data 26880字节。

3.控件对象结构体灯

lv_conf.h裁剪

内存

LVGL单独的内存池管理(动态内存heap大小),这里官方说最低2KB,官方推荐48KB,我们就设置为48KB,后续不够的话再增加即可

image-20250824163900744

控件

LVGL占用FreeRTOS的Heap优化

LVGL新版本和旧版本区别

LVGL v8.x 绘制完全由主任务 lv_task_handler 完成,无swdraw线程,所有绘制同步阻塞。

LVGL v9.x 后FreeRTOS单独引入swdraw线程(任务),把绘制工作转移到后台异步执行,主线程压力下降,响应更流畅。 需单独对swdraw任务进行监察,否则容易造成RTOS的Heap溢出

LVGL v9.x使用了OS时默认启用LV_USE_DRAW_SW

初始化lv_init时会调用lv_draw_sw_init,内部会创建一个任务swdraw,所有屏幕相关的像素渲染操作都是通过swdraw线程(任务)来完成的

image-20250829150851126

内部如果启用OS会创建swdraw线程,lv_thread_init内部是创建任务

image-20250829150802861

优化

之前在使用FreeRTOS+LVGL的时候,给FreeRTOS分配了15K的Heap,但是创建了3个任务8K左右就满了,我还疑问,经过日志输出后发现就是这个swdraw任务造成的

LVGL默认是分配8KB的堆栈给这个swdraw任务,具体为宏定义LV_DRAW_THREAD_STACK_SIZE

image-20250829150414406

实际运行过程中,还有1806*4 = 7224 Byte,大量的Heap空间浪费了,而我们的其他任务就可能因为Heap空间不够造成异常

image-20250829141117871

所以我们适当减少这个分配的空间,然后监视一下他的堆栈占用,如果不够的话再加。我这里改成了4K的堆栈,最后仍然剩余 782*4 = 3128 Byte,仍然很充足。这样就为RTOS节省了4KB的Heap空间

image-20250829151431006

image-20250829235835222