帧率

帧率指的是单位时间内所显示的帧数,方案的帧率统计是2s内送出去的平均帧数.
影响帧率的两大块:

  1. 页面渲染耗时

  2. LCD送数的时间

图形库刷新周期与LCD TE周期

  1. 图形库的刷新周期可以在config中进行配置,例如60HZ,则配置16ms.

  2. TE信号是由LCD产生的一个同步信号,当LCD完成一帧图像数据的显示后,就会发出一个TE脉冲信号. 这个信号标志着一帧图像显示周期的结束和下一帧图像显示周期的开始,当cpu收到TE信号后就开始启动送数. 一般建议图形库的刷新周期与TE周期保持一致,有时为了各项目驱动配置统一,也可配置图形库刷新周期小于TE周期.

影响因素:

  1. 需要太多软件参与的控件,如arc、label、chart(chart主要是很多的小控件,尺寸过小的填充也是软件处理)等等.

  2. 控件数量太多,由于LVGL使用的是递归,其效率很低,控件数量太多光是递归都需要花费不少时间.

  3. 图片数据量大,gpu占用过长,也会影响到该周期的这个耗时加长,所以尽可能减小图片的尺寸,如非必要的图片都去掉透明度, 容易触发全屏刷新的页面也建议尽可能不要使用全屏的背景图,否则每个周期都会把背景图渲染一遍(只要图片在屏幕上,均会渲染整个图片.

  4. ui线程严禁flash的读写操作,数据存储推荐使用app_db,该组接口会先将数据保存在内存中,睡眠或者关机时再保存. config中亦有实时写的配置"App db real-time write setting to falh", 需要注意如果开启了kvdbless(‘KVDB using self defined file’, 强烈推荐使用该配置)功能,则实时写的配置会失效.

优化:

  1. 增加渲染时的硬件支持,新版本的arc、label支持部分硬件加速,相比纯软件操作效率提升约50%左右, 需要注意arc的硬件支持需要更新最新版本,旧版本的用户联系SiFli团队,发布patch支持.

  2. 直接使用png叠图或者在缓存充足的情况下可以使用拍照的功能,即将严重影响刷新效率的控件初始化完成后将其拍成照片(snapshot)替换, 这样渲染该控件实际就变成了渲染照片,效率会有大幅度提升,更新数据时,只需将原控件数据更新后重新更新照片即可, 并且拍照后亦可以减少被拍对象内部的大量子控件递归耗时.

拍照相关的接口:

/**
 * 将一个obj的部分区域(area_p)拍成照片,照片数据存放在dsc中.
 */
void lv_refr_area_to_img_now(lv_obj_t *obj, const lv_area_t *area_p, lv_img_dsc_t *dsc);

/**
 * 将一个obj的部分区域(area_p)拍成一张可以缩放的照片,缩放后的照片数据存放在zoom_img中.
 */
void lv_refr_area_to_zoom_img_now(lv_obj_t *obj, const lv_area_t *area_p, lv_img_dsc_t *tmp_img, lv_img_dsc_t *zoom_img);

/**
 * 直接拷贝帧buf中的数据存放至img_dsc中.
 */
void lv_refr_dump_buf_to_img_now(lv_img_dsc_t *img_dsc);
  1. 拆分页面,对于某些长页面可以拆分成多页,可以单独拆分成小块或者整页,推荐使用‘lvsf_multlist’,该控件可以实现动态加载页面, 从而避免一个周期内处理太多数据引起卡顿,用法参照方案中的列表菜单app_mainmenu_list.c.以及一级页面app_tileview.c

  2. 针对需要旋转的图片,需要将对应的图片放入缓存中来旋转(nand 方案图片已经在PSRAM的缓存中),另外太大的旋转图片建议使用方案提供的"lvsf_splitpart"控件, 该控件充分利用了SRAM来提高旋转的效率,可以参考方案的指南针应用app_compass.c.

  3. 加快页面进出速度,将页面内容拆分,在resume handle中先初始化当前第一页的内容,其余的延后几个周期进行初始化,可以参照一级页面的做法.

  4. 选择合理的推屏配置,52/56系列推荐使用scheme7.

  5. 为了增加资源的cache命中率,一般建议字体缓存配置400 ~ 600k,剩余的空间全部分配给image cache

  6. 针对NAND的方案:
    nand方案在开机首次进入时因为缓存资源会比nor方案稍慢,缓存后运行效率高于nor.

    1. 推荐使用built-in的配置,直接访问图片资源,避免了旧方案中遍历文件系统的开销.

    2. 没有built-in的配置的版本,建议将图片资源放入各个应用的目录,同样是可以减少遍历文件找图的开销.

    3. gif,在某些滑动页面使用gif作为背景时,如果内存充足,可以直接将整个gif资源缓存,对应接口‘lv_agif_dec_create_comm’.

LCD送数

送数时长,以QSPI为例: QSPI 是4个数据线, 在RGB565模式下 一个像素点(16bit)数据需要’16/4’个时钟周期 送一帧全屏数据耗时(us) = 图形库宽 * 图形库高 * 每个像素需要的时钟周期 / QSPI速率 如16bit的410x494的屏,在48M的速率下:t = 410 x 494 * 4 / 48 000 000 = 16.87(ms),在这种条件下,帧率就不能跑60hz了,会导致lcd自刷新时,数据还未送完出现撕裂

动态加载示例

长列表

长列表demo参见app_mainmenu_list.c

list菜单使用‘lvsf_multlist’控件,页面加载采用动态加载的模式,根据PSRAM的大小分为:

  1. 所有元素全部加载以及全部拍照‘LV_SCRL_RESIDENCY_ALL’.

  2. 所有元素全部加载以及拍照只拍当前屏上的元素‘LV_SCRL_RESIDENCY_ELEMENT’.

注:列表的拍照在没有背景图的条件下直接使用’LV_IMG_CF_TRUE_COLOR‘即可,若有背景则需要配置成透明度模式’LV_IMG_CF_TRUE_COLOR_ALPHA‘

一级页面

一级页面的框架介绍参见平铺应用框架
demo参见app_tileview.c 这里主要介绍一些一级页面的几种优化配置:

  1. 在表盘页面上下拖动的速率如果较慢可以考虑上下拖动时暂停表盘的运行,config中直接使能‘APP_UPDONW_PAUSE_WATCHFACE’即可.

  2. 如果在各个子页面的resume中花费的时间较长,则可以使能延迟激活配置‘APP_TILEVIEW_RESUME_WITH_DELAY’,使能后,每次滑动结束会延迟几个周期激活页面, 延迟时间可以在代码中根据实际需求进行设置.

  3. 加快进入表盘页面的速率,可以直接使能‘APP_TILEVIEW_INIT_OPTIMIZE’配置,使能后,进入表盘时会只初始化当前页面, 其余页面(上下左右)均会在’2‘中的delay时间超时后进行初始化,注意事项参见’app_tileview.c’中的注释

  4. 为进一步加快一级页面左右滑动的速率,最新方案支持,将一级页面的子页面全部加载出来,需要配合’2‘、‘3’使用,这样左右来回滑动就省下初始化页面的时间.

注:部分旧版本如果没有以上配置,请联系SIFLI团队更新patch

调试方法

抓点工具sysview

使用方法参见文档Systemview工具抓点

调试指令

以下的finsh指令不带传参的都是发一次开启,再发一次关闭.

  1. 查看每个刷新周期耗时:task_time\

    1. 发送一次仅打印每个周期task handle的耗时

    2. 发送两次则在一的基础上打印indev 以及refr 的耗时

    3. 发送四次则关闭打印

  2. 查看文本的refr耗时:ft_time 返回‘ft_time: 1’表示设置成功
    进入文本页面时会打印该文本花费的时间以及文本长度(小于1ms的不打印):‘lv_label_set_text: ft time, 4(ms) size 10’

  3. 查看字体的log:ft_log

  4. 查看每个页面的msg handle(start/resume/pause/stop)耗时:‘app_sche_print_perf_tick 1’

  5. 查看一级页面msg handle(start/resume/pause/stop)耗时:‘tileview_fwk’

  6. 查看一级页面拍照耗时:‘trans_anim’

  7. 调试打印时间的接口:

    1. 毫秒级的可以直接使用’rt_tick_get’

    2. 微秒级使用‘cpu_get_hw_us’
      统计某个行为的耗时,直接使用上面的接口计算该行为前后的时间差即可