【LVGL进阶日记】② LVGL外部字库刷新速度优化

关注+星标公众号,不错过精彩内容
在这里插入图片描述
作者 | 量子君
微信公众号 | 极客工作室


【LVGL进阶日记】专栏目录
第一章 ① 开源LVGL在MCU上的移植
第二章 ② LVGL外部字库刷新速度优化


前言

LVGL 可以说是这两年才刚开始流行的一个小型开源嵌入式 GUI 库,具有界面精美,消耗资源小、可移植度高、响应式布局等特点,全库采用纯 C 语言开发,LVGL 库的更新速度非常快。

本章介绍了LVGL外部字库刷新速度优化的详细步骤。


一、问题背景/现状

  1. 在加载外部flash字库时,字库刷新速度明显慢于内部存储的字库
  2. 字库文件组成:索引区+段位区+偏移区+MAP点阵数据区

二、过程分析/优化的思路

  1. 首先怀疑SPI读取速度过慢,由于SPI速率设置为8M,故理论上不存在此问题。

  2. 字库显示原理分为LVGL内部处理流程和通过LITTLE FS读取外部字库信息两部分,通过LOG打印时间戳(NRF_RTC1->COUNTER),查看两部分的时间差异。(为排除干扰,内外字库只显示一个相同的文字)。

  3. 首先获取整个调度逻辑的耗时,只查看内外部字库差异点时间,故从_user_font_get_glyph_dsc2接口开始打印(注:此次使用的文字unicode码为0xad6d),到_user_font_get_bitmap2接口里的mg_font_get_mapdata函数(此函数是读取外部FLASH的函数)执行完毕结束。
    在这里插入图片描述
    在这里插入图片描述

  4. 通过log,发现外部字库需要32个时钟周期,内部字库需要16个,且_user_font_get_glyph_dsc2函数被调用了11次,user_font_get_bitmap 2被调用了3次。

  5. 查找步骤4两个函数被多次调用的原因,查看LVGL源码,根据调用次数及文字的字模信息发现,_user_font_get_bitmap2的调用次数与字模高度有关,LVGL会按照字模高度8的倍数进行多次调用,_user_font_get_glyph_dsc2函数会在获取字模的长宽高等数据时被多次调用;等于说要显示一个文字,如果字高为24,需要至少调用三次_user_font_get_glyph_dsc2,但获取外部点阵数据的函数每次都是将所有点阵信息一次性读取,等于重复了三次,内部字库虽也需读三次,但读片内FLASH速度快,不存在此问题,故此处为一个耗时点。

  6. 上述问题采用的方案是每次调用mg_font_get_mapdata时,先判断UNICODE码和文件ID是否变化,若无变化,将上次读取的信息返回即可,若不同,才将信息清空,重新获取,但改良后发现文字刷新速度仍然肉眼可见的延迟,可见仍存在其他问题。而经过上述步骤,目前仅剩读外部字库的代码逻辑与文件系统内部逻辑未排查,故继续排查这两部分。

  7. 获取map数据需要两步,先通过mg_font_get_map_infor读取存储map信息的4字节偏移地址数据,然后根据此偏移地址和map的字节数,通过mg_font_get_mapdata读取map数据,这两个步骤为必要步骤,故无法优化此过程。

  8. 分析低层文件系统逻辑,首先查看调用的文件系统读函数需要花费多长时间,下图三函数为读数据的入口函数,读数据有两部分,seek函数定位读起始地址,read函数读取数据,通过log打印时间,发现read函数耗时较长,由于底层挂载的读函数为SPI驱动函数,之前已排除SPI驱动本身问题,故将范围缩小到文件系统内部的读处理机制上。
    在这里插入图片描述

  9. 通过下图四log发现,一次文件的读操作,需要调用将近10次SPI读函数,读取一个map有两个读步骤(先读偏移地址,再根据偏移地址读数据),共调用近20次SPI读,继续查看文件系统读的源码,发现文件系统内部会从一个文件的末尾开始按照块的方式向前遍历,检索数据,为验证此逻辑,我们显示韩文字库最后一个字,发现时间变短,只消耗了一个时间周期,证明猜测正确。
    在这里插入图片描述

  10. 通过步骤九,证明数据的读取速度,与数据存于文件中的位置有关,由于索引信息位于文件最开头处,虽只有4字节,但耗费时间较长,而且大部分显示的文字也位于文件前端且大小为40字节,故总体时间变长。针对此问题,解决方案为将索引与数据分为两个文件存储,这样,索引的读取时间降低,可提高一定的速度,也可将文件中位于后端的生僻字去除,减小文件大小,减少遍历时间。

  11. 在系统整体优先级优化上,由于目前key与lvgl两线程优先级相同,LVGL的卡顿会影响KEY的响应,从而也给使用者造成卡顿现象,我们可以将按键优先级变高,或采用时间片轮询模式处理相同优先级任务,提高响应速度,从而使码表整体的响应速度提高。

三、结论和经验

  1. 实现LVGL的字库调用,逻辑图如下:
    在这里插入图片描述
  • get_glyph_dsc:获取字模的各种信息,包括字模高度宽度,偏移量,字节数等,此函数会在实现逻辑里多次调用;
  • get_glyph_bitmap:获取字模map数据,且调用次数需要通过调用get_glyph_dsc来获取;
  1. 文件系统内部检索逻辑:文件系统内部会从一个文件的末尾开始按照块的方式向前遍历,故越靠前的文件内容,会花费更多时间,且通过查阅资料,littlefs文件系统,有一种擦写均衡模式,不会将一个块写满再写下一个块,写入的数据越多,占的块越多,而读操作不会跨块进行,故读的次数增加。

四、附录

关于LITTLE FS读写性能的介绍参考以下文章:
LittleFs文件系统
关于littlefs文件系统的效率问题


总结

本章介绍了LVGL外部字库刷新速度优化的详细步骤。

关注公众号回复“加群”按规则加入技术交流群,回复“1024”查看更多内容。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

量子君

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值