LVGL内存优化

LVGL内存优化
THEDI裁剪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
把Range删掉后,这样就只会导出Symbols
中的字符0~9,代码也只剩2000行,同时Flash占用也只有10多KB
了
当然除了使用SquareLine生成,也可以使用lvgl官网提供的字体转换器得到字体的.c文件,就只会转换你想要的字符:
lv_conf.h
字体
这里是LVGL自带的一些字体,保证不报错即可,因为我们都是使用自定义字体
控件
不使用的控件不启用,节省资源
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
,后续不够的话再增加即可
控件
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线程(任务)来完成的
内部如果启用OS会创建swdraw线程,lv_thread_init
内部是创建任务
优化
之前在使用FreeRTOS+LVGL的时候,给FreeRTOS分配了15K的Heap,但是创建了3个任务8K左右就满了,我还疑问,经过日志输出后发现就是这个swdraw任务造成的
LVGL默认是分配8KB的堆栈给这个swdraw任务,具体为宏定义LV_DRAW_THREAD_STACK_SIZE
实际运行过程中,还有1806*4 = 7224 Byte,大量的Heap空间浪费了,而我们的其他任务就可能因为Heap空间不够造成异常
所以我们适当减少这个分配的空间,然后监视一下他的堆栈占用,如果不够的话再加。我这里改成了4K的堆栈,最后仍然剩余 782*4 = 3128 Byte,仍然很充足。这样就为RTOS节省了4KB
的Heap空间