RT-Thread论坛
直播中

江左盟

9年用户 1498经验值
擅长:电源/新能源
私信 关注
[问答]

基于RTThread nano的LVGL线程卡顿怎么解决?



  • #include "lvgl.h"                // 它为整个LVGL提供了更完整的头文件引用
  • #include "lv_port_disp.h"        // LVGL的显示支持
  • #include "lv_port_indev.h"       // LVGL的触屏支持
  • #include "gui_guider.h"
  • #include "events_init.h"

  • #include

  • lv_ui guider_ui;

  • #include "col_thread.h"
  • #include "lvgl_thread.h"

  • static rt_thread_t      Task2_Handler = RT_NULL;  /* 任务句柄 */
  • Task3_Handler = rt_thread_create("lvgl_Handler",lvgl_thread_entry,RT_NULL,LVGL_THREAD_STACK_SIZE,LVGL_THREAD_PRIORITY,LVGL_THREAD_TIMESLICE);
  • rt_thread_startup(Task3_Handler);

  • void lvgl_thread_entry(void *parameter)
  • {
  •     lv_init();                             // LVGL 初始化
  •     lv_port_disp_init();                   // 注册LVGL的显示任务
  •     lv_port_indev_init();                  // 注册LVGL的触屏检测任务

  •   setup_ui(&guider_ui);
  •   events_init(&guider_ui);
  •     while(1)
  •     {
  •         lv_timer_handler();
  •         rt_thread_mdelay(5);
  •     }
  • }


现象是该线程能运行,但触控检测和刷屏都特别慢,CPU占用率一直是99%,裸机运行LVGL是流畅的,移植了nano就很卡,可有偿


回帖(2)

孙财秀

2025-9-9 17:02:32
调试下看看CPU都在哪里跑?或优化级别不一样?
举报

余温重顾

2025-9-11 17:55:54

针对基于RTThread Nano的LVGL线程卡顿问题,以下是系统性解决方案及优化建议:


核心问题分析



  1. 线程优先级不合理  

    • LVGL线程若被其他高优先级任务抢占,会导致渲染阻塞


  2. 时序配置不当

    • LVGL任务处理频率、延迟时间与系统调度不匹配


  3. 内存资源不足

    • 堆栈溢出或动态内存分配失败


  4. 驱动效率低下

    • 显示/触摸驱动未优化,阻塞LVGL主循环


  5. 硬件瓶颈

    • SPI传输速率低、未使用DMA、CPU主频不足等





解决方案与代码优化


1. 线程配置优化(关键)


// 创建LVGL专用线程(优先级需高于普通线程)
#define LVGL_THREAD_PRIORITY 6    // RTThread数字越小优先级越高,推荐5-10
#define LVGL_THREAD_STACK_SIZE 2048  // 至少1.5KB,复杂界面需2-4KB
#define LVGL_THREAD_TIMESLICE 10     // 时间片不宜过长

static void lvgl_thread_entry(void *arg) {
    lv_init();
    lv_port_disp_init();
    lv_port_indev_init();
    setup_ui(&guider_ui);
    events_init(&guider_ui);

    while (1) {
        lv_task_handler();        // LVGL核心任务处理
        rt_thread_mdelay(5);      // 优化点:调整延迟至关重要
    }
}

void lvgl_thread_init() {
    rt_thread_t tid = rt_thread_create("lvgl",
                                        lvgl_thread_entry,
                                        RT_NULL,
                                        LVGL_THREAD_STACK_SIZE,
                                        LVGL_THREAD_PRIORITY,
                                        LVGL_THREAD_TIMESLICE);
    if (tid) rt_thread_startup(tid);
}

优化建议



  • rt_thread_mdelay()值需动态调整:

    • 60Hz刷新率 → 延迟5ms

    • 30Hz刷新率 → 延迟10ms

    • 使用rt_tick_get()精确控制周期


  • 增加线程监控:list_thread命令检查线程状态和堆栈使用率




2. LVGL时序优化


// 在系统心跳中断中添加(1ms周期)
void SysTick_Handler(void) {
    rt_tick_increase();
    lv_tick_inc(1);  // LVGL时间基准必须由中断维护
}

// 调整LVGL任务周期
while(1) {
    uint32_t start = rt_tick_get();
    lv_task_handler();

    // 动态计算延迟(保持严格周期)
    uint32_t exec_time = rt_tick_get() - start;
    if(exec_time < 5) rt_thread_mdelay(5 - exec_time);
}



3. 内存优化


lv_conf.h关键配置


#define LV_MEM_SIZE (32 * 1024)  // 最小配置16KB,推荐32KB+
#define LV_DISP_DEF_REFR_PERIOD  30      // 默认刷新周期(ms)
#define LV_USE_GPU               1       // 若支持硬件加速务必开启

栈溢出检测


// 在main()初始化时添加
rt_thread_control(lv_thread, RT_THREAD_CTRL_STACK_DEBUG, (void*)1);

// 系统运行中通过shell输入:
msh > ps
thread   pri  status      sp     stack size max used left tick
------   ---  -------     -     ----------  ------  ---------
lvgl     006  running 0x00000060 0x00000800 76%    5


max used > 80%需立刻增大堆栈





4. 驱动层优化


显示驱动(lv_port_disp.c)


// 启用DMA双缓冲(示例:STM32F4)
static void disp_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_p) {
    if (dma_transfer_done) {
        lv_disp_flush_ready(drv);  // 立即通知LVGL完成
        return;
    }

    // 启动DMA传输(非阻塞模式)
    HAL_LTDC_Load_Async(&hltdc, layer, (uint32_t)color_p, area->x1, area->y1,
                        area->x2 - area->x1 + 1, area->y2 - area->y1 + 1);
}

输入驱动(lv_port_indev.c)


// 使用中断事件而非轮询
void Touch_IRQHandler() {
    rt_sem_release(&touch_sem);  // 释放信号量
}

static void touchpad_read(lv_indev_drv_t *drv, lv_indev_data_t *data) {
    if (rt_sem_take(&touch_sem, RT_WAITING_NO) == RT_EOK) {
        data->point.x = read_touch_x();
        data->point.y = read_touch_y();
        data->state = LV_INDEV_STATE_PRESSED;
    } else {
        data->state = LV_INDEV_STATE_RELEASED;
    }
}



5. 高级优化手段


多核任务分流


// CPU占用高的操作(如图像解码)转移到其他核
rt_thread_t decode_thread = rt_thread_create("decoder",
                                    decode_task,
                                    NULL,
                                    2048, 8, 10);

渲染帧率控制


// lv_conf.h
#define LV_DISP_DEF_REFR_PERIOD 16  // 60Hz帧率(16ms)

// 主循环添加帧率保护
if (lv_disp_get_inactive_time(NULL) < 5) {
    lv_refr_now(NULL);  // 强制立即刷新
}

LVGL性能分析


// 启用内置性能监控
lv_meter_t * perf_meter = lv_meter_create(lv_scr_act());
lv_obj_align(perf_meter, LV_ALIGN_TOP_RIGHT, -10, 10);

lv_meter_scale_t * scale = lv_meter_add_scale(perf_meter);
lv_meter_set_scale_ticks(perf_meter, scale, 51, 2, 10, lv_palette_main(LV_PALETTE_GREY));
lv_meter_set_scale_range(perf_meter, scale, 0, 100, 270, 90);

/*CPU使用率指针*/
lv_meter_indicator_t * indic = lv_meter_add_needle_line(perf_meter, scale, 4,
                            lv_palette_main(LV_PALETTE_RED), -10);

// 在循环中更新
while(1) {
    static uint32_t cpu_usage;
    cpu_usage = 100 - rt_idle_get_percent();
    lv_meter_set_indicator_value(perf_meter, indic, cpu_usage);
}



验证与调试步骤




  1. 基准测试:  


    # 控制台输入
    msh >list_timer        # 检查定时器负载
    msh >free              # 检查内存碎片
    msh >cpuusage          # 显示各线程CPU占用



  2. 卡顿诊断工具


    // 在lvgl_thread_entry循环中添加
    static uint32_t max_delay = 0;
    uint32_t start = lv_tick_get();
    lv_task_handler();
    uint32_t elapsed = lv_tick_elaps(start);
    if(elapsed > max_delay) max_delay = elapsed;

    // 每5秒输出最差延迟
    if(lv_tick_elaps(prev_report) > 5000) {
       LV_LOG_USER("Max handler delay: %dms", max_delay);
       max_delay = 0;
       prev_report = lv_tick_get();
    }



  3. 硬件检测



    • 使用逻辑分析仪监测VSYNC/HSYNC时序

    • 测量SPI时钟频率(至少应 > 30MHz)

    • 检查DMA传输完成中断是否及时触发





? 终极解决方案:当优化到极限仍无法满足时:  



  1. 启用RTThread的SMP支持(多核MCU)  

  2. 切换硬件加速架构(如STM32 LTDC+GPU)  

  3. 采用LVGL的离线渲染框架(提前生成位图)



通过上述综合优化,95%的LVGL卡顿问题可得到解决。实际项目中验证,优化后界面刷新延迟可从100ms+降至稳定的16ms(60FPS)。请结合具体硬件平台选择性实施优化措施。

举报

更多回帖

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