1. 从LVGL8到LVGL9:一个“省内存”引发的“血案”
最近在搞一个嵌入式GUI项目,用的STM32,板子上挂了块480x272的RGB565屏幕。项目原本基于LVGL8开发,界面做得挺花哨,图片素材一大堆。本来跑得好好的,直到老板要求再加几个带复杂图标的新页面。我一编译,好家伙,固件体积直接爆了,链接器报错提示.rodata段放不下——我们芯片内置的Flash只有1MB,而那片宝贵的8MB SDRAM是专门用来做帧缓冲和动态内存的,存放只读的图片数据实在是有点浪费。
就在我纠结是求老板换芯片(预算和时间都不允许)还是狠心砍掉一些视觉效果时,我注意到了LVGL9的一个新特性:RLE(Run-Length Encoding,游程编码)图片压缩。官方文档和社区里都说,对于UI中常见的大色块图标、背景图,RLE压缩率非常可观,能大幅减少图片资源占用的Flash空间。这简直是救命稻草!没多想,我立刻决定将项目从LVGL8升级到LVGL9。
移植过程还算顺利,LVGL9的API大部分兼容LVGL8,花了大半天时间调整和测试,基础功能都跑通了。接下来就是重头戏:处理图片资源。我兴冲冲地找到LVGL9官方提供的图片转换工具 LVGLImage.py,按照文档,对我所有的PNG图片执行了转换命令,目标格式是BIN文件,方便我直接从存储介质加载到内存。命令大概是这样的:
python LVGLImage.py --ofmt BIN --cf RGB565 --align 4 --compress RLE image1.png
这里解释一下几个参数:--ofmt BIN 指定输出二进制文件;--cf RGB565 对应我的屏幕色彩格式;--align 4 是为了Flash读写效率做的4字节对齐;--compress RLE 就是启用RLE压缩。
转换完成后,我得到了一个 image1.bin 文件。按照我在LVGL8里的老经验,以及LVGL官方示例中常见的做法,我写下了类似下面的代码,准备把这个BIN文件的数据(已经预先加载到SDRAM的某个地址)显示出来:
// 假设 bin_data 是指向SDRAM中image1.bin文件内容的指针
// 假设 bin_size 是文件大小
static lv_img_dsc_t img_dsc;
lv_memset(&img_dsc, 0, sizeof(lv_img_dsc_t));
img_dsc.header.w = 480; // 图片宽度
img_dsc.header.h = 272; // 图片高度
img_dsc.header.cf = LV_COLOR_FORMAT_RGB565; // 色彩格式
img_dsc.header.magic = LV_IMAGE_HEADER_MAGIC; // 必须的魔数
img_dsc.data_size = bin_size; // 数据大小 = 文件大小
img_dsc.data = (const uint8_t*)bin_data; // 数据指针 = 文件起始地址
lv_obj_t * img = lv_img_create(lv_scr_act());
lv_img_set_src(img, &img_dsc);
lv_obj_center(img);
代码逻辑清晰明了:我手动构造了一个 lv_img_dsc_t 描述符,告诉LVGL图片的宽、高、格式和数据在哪里。在LVGL8时代,对于原始的、未压缩的图片数据,或者一些简单的自定义格式,这么干完全没问题。我信心满满地编译、下载、运行……结果屏幕上空空如也,图片根本没出来!
当时我的第一反应是:数据加载错了?指针不对?SDRAM访问有问题?我用调试器反复确认,bin_data 指针指向的地址正确,数据也的确被完整地读到了SDRAM里。宽度高度色彩格式都检查了无数遍,完全匹配。那么问题出在哪呢?难道LVGL9的RLE压缩图片,不能像普通图片数据那样直接用了?这场本以为能“省内存”的升级,开局就给我挖了个坑。
2. 抽丝剥茧:为什么SD卡和C数组能行,内存加载就不行?
图片显示不出来,最直接的调试方法就是对比验证。我的项目里已经移植了FatFs文件系统,可以从SD卡读取文件。于是,我换了一种加载方式,直接用LVGL的文件系统接口来显示这个 image1.bin:
lv_obj_t * img = lv_img_create(lv_scr_act());
lv_img_set_src(img, “S:/images/image1.bin”); // “S:” 是SD卡的路径前缀
lv_obj_center(img);
这次,图片竟然正常显示出来了!这说明 image1.bin 这个文件本身是没问题的,转换工具和RLE压缩算法也是OK的。问题肯定出在我手动构造描述符、从内存加载数据这


443

被折叠的 条评论
为什么被折叠?



