最近做横向用到了ESP32P4平台,其中一个任务是驱动一块800*1280的屏幕,然后用LVGL在屏幕上做横屏的UI交互。为确保工程可以流畅运行,现对LVGL的性能做测试。
测试工程
因为开发开发使用的是微雪的ESP32-P4-WIFI6开发板,因此直接使用其给出的LVGL例程。(链接是微雪给的全部示例工程,我们使用第8个(08_lvgl_demo_v9)。
这份代码使用的LVGL版本为9.4.0(该版本支持了PPA加速旋转和渲染的功能)。测试代码如下(添加了测试结果的控制台输出):
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "nvs_flash.h"
#include "nvs.h"
#include "esp_log.h"
#include "esp_err.h"
#include "esp_check.h"
#include "esp_memory_utils.h"
#include "lvgl.h"
#include "bsp/esp-bsp.h"
#include "bsp/display.h"
#include "bsp_board_extra.h"
#include "lv_demos.h"
static const char *TAG = "BENCHMARK";
// Benchmark result callback function
static void benchmark_end_callback(const lv_demo_benchmark_summary_t *summary)
{
ESP_LOGI(TAG, "========================================");
ESP_LOGI(TAG, "LVGL Benchmark Results");
ESP_LOGI(TAG, "========================================");
ESP_LOGI(TAG, "");
// Print per-scene results
ESP_LOGI(TAG, "Individual Scene Results:");
ESP_LOGI(TAG, "Name | Avg. CPU | Avg. FPS | Render Time | Flush Time");
ESP_LOGI(TAG, "----------------------------------------------------");
for(size_t i = 0; summary->scenes[i].create_cb; i++) {
if(summary->scenes[i].measurement_cnt > 0) {
const uint32_t cnt = summary->scenes[i].measurement_cnt;
const uint32_t cpu = summary->scenes[i].cpu_avg_usage / cnt;
const uint32_t fps = summary->scenes[i].fps_avg / cnt;
const uint32_t render = summary->scenes[i].render_avg_time / cnt;
const uint32_t flush = summary->scenes[i].flush_avg_time / cnt;
ESP_LOGI(TAG, "%-20s | %3u%% | %3u FPS | %4u ms | %4u ms",
summary->scenes[i].name, cpu, fps, render, flush);
}
}
ESP_LOGI(TAG, "");
ESP_LOGI(TAG, "Overall Average Results:");
ESP_LOGI(TAG, "----------------------------------------------------");
if(summary->valid_scene_cnt > 0) {
const uint32_t avg_cpu = summary->total_avg_cpu / summary->valid_scene_cnt;
const uint32_t avg_fps = summary->total_avg_fps / summary->valid_scene_cnt;
const uint32_t avg_render = summary->total_avg_render_time / summary->valid_scene_cnt;
const uint32_t avg_flush = summary->total_avg_flush_time / summary->valid_scene_cnt;
const uint32_t total_time = avg_render + avg_flush;
ESP_LOGI(TAG, "Average CPU Usage: %u%%", avg_cpu);
ESP_LOGI(TAG, "Average FPS: %u", avg_fps);
ESP_LOGI(TAG, "Average Render Time: %u ms", avg_render);
ESP_LOGI(TAG, "Average Flush Time: %u ms", avg_flush);
ESP_LOGI(TAG, "Total Average Time: %u ms", total_time);
ESP_LOGI(TAG, "Measured Scenes: %d", summary->valid_scene_cnt);
} else {
ESP_LOGW(TAG, "No valid scene measurements available");
}
ESP_LOGI(TAG, "========================================");
ESP_LOGI(TAG, "Benchmark Completed!");
ESP_LOGI(TAG, "========================================");
}
void app_main(void)
{
bsp_display_cfg_t cfg = {
.lv_adapter_cfg = ESP_LV_ADAPTER_DEFAULT_CONFIG(),
.rotation = ESP_LV_ADAPTER_ROTATE_0,
.tear_avoid_mode = ESP_LV_ADAPTER_TEAR_AVOID_MODE_TRIPLE_PARTIAL,
//.tear_avoid_mode = ESP_LV_ADAPTER_TEAR_AVOID_MODE_TRIPLE_FULL,
.touch_flags = {
.swap_xy = 0,
.mirror_x = 0,
.mirror_y = 0
}};
bsp_display_start_with_config(&cfg);
bsp_display_backlight_on();
// 设置基准测试结束回调函数
lv_demo_benchmark_set_end_cb(benchmark_end_callback);
bsp_display_lock(-1);
// lv_demo_music();
lv_demo_benchmark();
// lv_demo_widgets();
bsp_display_unlock();
}
打补丁
需要注意,如果按照这个配置并且希望将屏幕旋转90°,除了修改ESP_LV_ADAPTER_ROTATE_0为ESP_LV_ADAPTER_ROTATE_90外(事实上如果真的要用横屏还需要把swap_xy 和mirror_x 这两项触摸屏设置改为1),还需要根据注释的提示给其打上补丁,否则测试程序会报错。具体的,去github相应位置,把补丁down下来。然后到esp-idf的路径下运行如下代码即可(注意文件的路径,因为我直接拷贝到esp-idf中,所以才这么写):
git apply 0001-bugfix-lcd-Fixed-PPA-freeze.patch
修复CPU占用的显示Bug
此外,还需要修复CPU显示的Bug,在CmakeLists.txt中添加如下代码即可:
add_compile_definitions(CONFIG_LV_SYSMON_GET_IDLE=lv_timer_get_idle)
添加后的CmakeLists.txt全部代码如下:
# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
set(EXTRA_COMPONENT_DIRS
./components/bsp_extra
)
add_compile_definitions(CONFIG_LV_SYSMON_GET_IDLE=lv_timer_get_idle)# 修复CPU占用率全部显示100%的问题
add_compile_options(-Wno-format)
project(lvgl_demo_v9)
正式测试
三缓冲+全局刷新+0°旋转
测试结果如下:
Average CPU Usage: 93%
Average FPS: 26
Average Render Time: 43 ms
Average Flush Time: 0 ms
Total Average Time: 43 ms
Measured Scenes: 16
可以看到在16个场景中使用“三缓冲+全局刷新+0°旋转”的平均帧为26(如果想了解具体场景的情况可以自己运行一遍代码看看输出,这里没有全部贴出来)。
三缓冲+局部刷新+0°旋转
Average CPU Usage: 92%
Average FPS: 32
Average Render Time: 28 ms
Average Flush Time: 9 ms
Total Average Time: 37 ms
Measured Scenes: 16
将全局缓冲改为局部刷新之后,平均帧率上升了6帧。
三缓冲+局部刷新+旋转90°(不使用PPA加速)
Average CPU Usage: 93%
Average FPS: 23
Average Render Time: 34 ms
Average Flush Time: 19 ms
Total Average Time: 53 ms
Measured Scenes: 16
而设置软件旋转90°后,平均帧率降低将下降9帧左右,性能下跌接近30%。可见,在可能的情况下,选择支持硬件旋转的屏幕最佳。如果屏幕不支持硬件旋转,那么选择自己应用中需要的那个摆放角度的屏幕最好,像竖屏横用这种操作就很蛋疼。
三缓冲+局部刷新+旋转90°(使用PPA加速)
LVGL9.4已经官方支持了PPA加速,理论上来说如果正确设置的话应该和官方说明一样可以增加帧率或者减少CPU占用30%才对。
然而官方给的说明链接点进去是404,而按照esp32p4使用PPA加速教程这篇博客的方法做设置之后发现benchmark程序在部分场景中存在显示错误问题,而且最终运行的平均帧率非但没有增加反而减少了一点,CPU占用也逆天的上升了一点。。。
说明文档
lvgl/docs/src/CHANGELOG.rst at v9.4.0 · lvgl/lvgl

因此,合理怀疑这一版本的PPA加速还存在问题(比较是第一版支持这个的),当然也可能是我自己的操作有误。这些问题需要看更底层的代码,后面有需要再进一步研究。当然,也有可能等LVGL9.5出来就好了。。。
三缓冲+局部刷新+旋转90°+编译器优化策略修改为Debug
因为工程过程中需要用到串口组件,结果又遇到了ESP-IDF的新bug(编译器bug,相当隐蔽。。。),github给出的暂时的解决方法是修改编译器的优化选项,从performance改为别的。。。新平台的坑是真的多,以后做项目得注意先查一下甲方用的平台是什么时候出来的。。。像P4这种半年内出来的板子得特别小心。
Average CPU Usage: 93%
Average FPS: 21
Average Render Time: 41 ms
Average Flush Time: 19 ms
Total Average Time: 60 ms
Measured Scenes: 16
三缓冲+局部刷新+旋转90°+编译器优化策略修改为Size
Average CPU Usage: 93%
Average FPS: 21
Average Render Time: 40 ms
Average Flush Time: 19 ms
Total Average Time: 59 ms
Measured Scenes: 16
可以看到,相比performance,其他两种编译器的优化策略会使得帧率表现下降2帧左右。因此如果需要高帧率最好还是时刻关注编译器的bug什么时候被修好。。。
172

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



