RT-Thread论坛
直播中

ejlwj

9年用户 979经验值
擅长:处理器/DSP
私信 关注
[问答]

lvgl运行卡顿,测试发现lv_task_handler执行时间过长是什么原因?

软件:RTT4.1.1 + LVGL8.3.10
硬件:STM32F103VGT6
LCD:分辨率320*240,FSMC+16BIT控制
LCD刷图速度还能接受,全屏在30ms左右,但是运行lvgl菜单时(尤其是按下按键切到延伸的按钮时)非常卡顿。
经过测试发现lv_task_handler()在有控件需要更新时绘制时间超长!差不多要3、400ms以上,感觉这个不是很正常啊,锯齿阴影之类的我都关了,就算控件多一点(其实也不是很多,也就20个左右)也不至于这么久吧?
这是我的测试代码:

  • static void lvgl_thread_entry(void *parameter)
  • {
  • #if LV_USE_LOG
  •     lv_log_register_print_cb(lv_rt_log);
  • #endif /* LV_USE_LOG */
  •     lv_init();
  •     lv_port_disp_init();
  •     lv_port_indev_init();
  •     lv_user_gui_init();

  •     /* handle the tasks of LVGL */
  •     while(1)
  •     {
  •         uint32_t tick = lv_tick_get();
  •         lv_task_handler();
  •         uint32_t tick_end = lv_tick_get();
  •         if (tick_end != tick)
  •         {
  •             rt_kprintf("[%d] lvgl : %dmsn", tick_end, tick_end - tick);
  •         }
  •         rt_thread_mdelay(LV_DISP_DEF_REFR_PERIOD);
  •     }
  • }


这是运行日志:

  • SystemCoreClock: 72000000 Hz
  • LVGL button encoder initialized
  • [2215]: points(64000): 28 ms
  • [2265]: points(12800): 6 ms
  • [2270] lvgl : 326ms
  • Menu setting created
  • [151756]: points(64000): 27 ms
  • [151817]: points(12800): 6 ms
  • [151822] lvgl : 449ms
  • [155677]: points(22400): 10 ms
  • [155682] lvgl : 192ms
  • [156942]: points(64000): 28 ms
  • [157013]: points(12800): 6 ms
  • [157019] lvgl : 1328ms
  • [160858]: points(1260): 1 ms
  • [160877] lvgl : 130ms
  • [161339]: points(64000): 28 ms
  • [161400]: points(12800): 6 ms
  • [161405] lvgl : 519ms
  • [162939]: points(38400): 17 ms
  • [162944] lvgl : 330ms
  • [164478]: points(38400): 17 ms
  • [164484] lvgl : 332ms
  • [165234]: points(38400): 18 ms
  • [165239] lvgl : 328ms
  • [419017]: points(33280): 15 ms
  • [419022] lvgl : 245ms



这是我的配置

  • #define LV_COLOR_DEPTH          16
  • // #define LV_USE_PERF_MONITOR     1 // 显示帧率
  • #define LV_HOR_RES_MAX          320
  • #define LV_VER_RES_MAX          240

  • /* 降低系统开销 */
  • #define LV_USE_SHADOW 0
  • #define LV_USE_GRADIENT 0
  • #define LV_USE_ANTIALIAS 0




回帖(2)

刘悌耀

2025-9-18 17:23:41
最终发现核心问题还是MCU主频跟不上,绘制控件远比想象中要浪费时间
举报

胖子的逆袭

2025-9-23 17:00:15

根据您描述的问题,lv_task_handler 执行时间过长导致界面卡顿,可能由以下原因及解决方案构成:


主要原因分析:




  1. 绘图缓冲区配置不当



    • LVGL 使用绘图缓冲区 (VDB) 存储渲染结果,若缓冲区过小,LVGL 需分块刷新,导致多次刷屏调用。

    • 全屏刷新需 30ms,若缓冲区仅允许每次渲染 10 行,则需 32 次刷屏(240/10 * 30ms ≈ 768ms),与您观察的 300ms~400ms 接近。




  2. 刷新区域未优化



    • 控件状态变化(如按钮按下)可能导致大面积区域标记为脏区,触发全屏刷新。

    • 复杂控件(如带透明、渐变)会增加渲染负载。




  3. 硬件性能瓶颈



    • STM32F103@72MHz 处理 320x240 分辨率本身压力较大。

    • FSMC 总线配置或 LCD 驱动未优化,导致刷屏效率低下。






优化方案:


1. 增大绘图缓冲区(关键步骤)


lv_conf.h 中调整配置:


// 至少分配 1/10 屏幕大小的缓冲区
#define LV_VDB_SIZE         (320 * 24)  // 24行缓冲区(约10%屏幕)
#define LV_VDB_ADR          0           // 动态分配内存

// 启用双缓冲(若RAM足够)
#define LV_VDB_DOUBLE       1

注意:STM32F103VGT6 有 96KB RAM,3202402(双缓冲)需 150KB,不可行。建议用部分缓冲并优化尺寸。


2. 优化渲染流程


// lv_conf.h
#define LV_COLOR_DEPTH      16      // 确保颜色深度匹配LCD(16bit)
#define LV_USE_GPU          0       // F103无硬件GPU,关闭
#define LV_USE_SHADOW       0       // 关闭阴影
#define LV_USE_OPA_SCALE    0       // 关闭透明度缩放

3. 优化刷屏驱动


确保 FSMC 配置为最高速度:


// RT-Thread 的 LCD 驱动中优化写数据函数
void lcd_fast_fill(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) {
    LCD->RAM = color;  // 预写颜色值
    for (int y = y1; y <= y2; y++) {
        for (int x = x1; x <= x2; x++) {
            *(__IO uint16_t *)(BANK_LCD_D) = color;  // 直接操作FSMC数据地址
        }
    }
}

4. 精简界面设计



  • 减少复杂控件(如按钮组、列表)。

  • 避免深层嵌套布局。

  • 使用简单样式替代渐变/透明效果。


5. 监控脏区刷新


添加调试代码检查刷新区域:


void monitor_flush_cb(lv_disp_drv_t *disp_drv, const lv_area_t *area) {
    static uint32_t last_time = 0;
    uint32_t now = rt_tick_get();
    uint32_t elapsed = now - last_time;
    last_time = now;

    rt_kprintf("Refresh: [%d,%d]->[%d,%d] Time:%d msn",
        area->x1, area->y1, area->x2, area->y2, elapsed);
}

在驱动注册时设置:


disp_drv.flush_cb = monitor_flush_cb;

6. 任务调度优化


确保 LVGL 线程优先级足够高(高于按键扫描线程):


rt_thread_t lvgl_tid = rt_thread_create("lvgl", lvgl_thread_entry, RT_NULL, 4096, 6, 10);
rt_thread_startup(lvgl_tid);

7. 启用 LVGL 渲染缓存


// lv_conf.h
#define LV_USE_DRAW_SW 1
#define LV_DRAW_SW_COMPLEX 0  // 关闭高级绘图功能



建议验证步骤:



  1. 调整缓冲区大小:逐步增加 LV_VDB_SIZE 测试卡顿改善情况。

  2. 简化测试界面:创建仅含 1 个按钮的页面,测试响应时间。

  3. 测量刷屏时间:用示波器/逻辑分析仪检查 FSMC 的 WR 信号间隔,优化时序配置。

  4. 检查内存分配:确保 lv_mem_alloc 未使用低效算法(可换为 RT-Thread 小内存管理)。



性能预期:优化后,单个按钮刷新应能控制在 50ms 内。若仍卡顿,需考虑升级硬件(如 STM32F4 系列)或降低分辨率。



通过上述优化,应能显著降低 lv_task_handler 的执行时间,提升界面流畅度。

举报

更多回帖

发帖
×
20
完善资料,
赚取积分