由于LVGL是一个免费开源的图形库,且提供了嵌入式易于使用的图形元素、良好的视觉效果和低内存占用等GUI所需的功能。故将LVGL移植至正点原子RK3568开发板,开发一个简单的车辆仪表项目。

1. git代码获取

本文章所克隆的为V8.2的内容,后期再克隆最新版本吧!!!
首先,克隆lv_port_linux仓库:

git clone -b release/v8.2 https://github.com/lvgl/lv_port_linux.git

lv_port_linux仓库克隆完成后,执行如下指令克隆lvgl及lv_drivers:

git submodule update --init --recursive

2. lvgl 配置

lvgl配置主要是针对lv_conf.h与lv_drv_conf.h的内容进行配置。

  • lv_conf.h用于配置LVGL图形库本身如内存、界面、组件等功能;
  • lv_drv_conf.h用于配置LVGL所提供的硬件如显示屏、触摸、输入等驱动。

因此,根据实际需求将对上述两个文件进行配置,详细配置如下所示:

2.1 lv_confg.h配置

  1. 使能文件内容
    将开头的 #if 0 更改为 #if 1 以使能其内容
    在这里插入图片描述

  2. 修改色彩深度
    根据自己设备所能支持的色彩深度进行设置:
    在这里插入图片描述

  3. 使能显存
    将LV_MEM_CUSTOM设置为1, 使系统能为LCD屏分配运行显存:
    在这里插入图片描述

  4. 修改屏幕刷新时间
    LVGL提供屏幕刷新时间设定,可根据自己需求进行刷新与读周期时间的更改:
    在这里插入图片描述

  5. 使能demo
    LVGL提供测试demo,可以使能LVGL所提供的demo进行功能验证:
    在这里插入图片描述

     注意:在lvgl_conf.h中还提供丰富的功能配置,可根据实际需求自行配置!!!
    

2.2 lv_drv_conf.h配置

  1. 使能文件内容
    将开头的 #if 0 更改为 #if 1 以使能其内容
    在这里插入图片描述
  2. 显示驱动
    由于开发板的显示系统使用DRM(Direct Rendering Module)框架,因此需关闭USE_FBDEV并打开USE_DRM,配置详细如下图所示:
    在这里插入图片描述
    如何判断显示系统使用何种框架:
  • 输入如下命令,查看屏幕是否出现雪花,若出现雪花则使用了fb0, 即FBD框架
cat /dev/random > /dev/fb0
  1. 触摸驱动
    若需使用触摸功能,则需要对触摸进行配置:
    a. 使能触摸
    将USE_EVDEV置1,打开触摸功能:
    在这里插入图片描述

    b. 修改驱动
    根据开发板的实际触摸驱动进行EVEDV_NAME的修改。如下图所示,开发板触摸设备为event2,从而将EVEDV_NAME的内容修改为 ”/dev/input/event2"。
    在这里插入图片描述
    若不知道当前触摸屏驱动名,则可通过hexdump命令查询当前触摸驱动,如输入hexdump /dev/input/event2后触摸屏幕,若存在数据显示则代表为设备驱动,否则继续测试其他设备驱动,adb显示效果如图所示:
    在这里插入图片描述

3. main.c 修改

main.c为lvgl中的默认程序,特此用于测试lvgl移植是否完成。同时,由于开发采用drm框架进行显示,所以需要对main.c进行修改,详细修改内容如下:

#include "lvgl/lvgl.h"
#include "lvgl/demos/lv_demos.h"
#include "lv_drivers/display/drm.h" /* 添加drm.h头文件 */
#include "lv_drivers/indev/evdev.h"
#include <unistd.h>
#include <pthread.h>
#include <time.h>
#include <sys/time.h>

#define DISP_BUF_SIZE (1080 * 1920) /* 根据实际屏幕大小进行设置 */

int main(void)
{
    /*LittlevGL init*/
    lv_init();

    /*Linux frame buffer device init*/
    drm_init(); // fvdev_init -> drm_init

    /*A small buffer for LittlevGL to draw the screen's content*/
    static lv_color_t buf[DISP_BUF_SIZE];

    /*Initialize a descriptor for the buffer*/
    static lv_disp_draw_buf_t disp_buf;
    lv_disp_draw_buf_init(&disp_buf, buf, NULL, DISP_BUF_SIZE);

    /*Initialize and register a display driver*/
    static lv_disp_drv_t disp_drv;
    lv_disp_drv_init(&disp_drv);
    disp_drv.draw_buf   = &disp_buf;
    disp_drv.flush_cb   = drm_flush; /* fbdev_flush -> drm_flush */
    disp_drv.hor_res    = 1080;
    disp_drv.ver_res    = 1920;
    lv_disp_drv_register(&disp_drv);

    evdev_init();
    static lv_indev_drv_t indev_drv_1;
    lv_indev_drv_init(&indev_drv_1); /*Basic initialization*/
    indev_drv_1.type = LV_INDEV_TYPE_POINTER;

    /*This function will be called periodically (by the library) to get the mouse position and state*/
    /*未使用鼠标,故注释该程序段*/
    #if 0
    indev_drv_1.read_cb = evdev_read;
    lv_indev_t *mouse_indev = lv_indev_drv_register(&indev_drv_1);


    /*Set a cursor for the mouse*/
    LV_IMG_DECLARE(mouse_cursor_icon)
    lv_obj_t * cursor_obj = lv_img_create(lv_scr_act()); /*Create an image object for the cursor */
    lv_img_set_src(cursor_obj, &mouse_cursor_icon);           /*Set the image source*/
    lv_indev_set_cursor(mouse_indev, cursor_obj);             /*Connect the image  object to the driver*/
    #endif


    /*Create a Demo*/
    lv_demo_widgets();

    /*Handle LitlevGL tasks (tickless mode)*/
    while(1) {
        lv_timer_handler();
        usleep(5000);
    }

    return 0;
}

/*Set in lv_conf.h as `LV_TICK_CUSTOM_SYS_TIME_EXPR`*/
uint32_t custom_tick_get(void)
{
    static uint64_t start_ms = 0;
    if(start_ms == 0) {
        struct timeval tv_start;
        gettimeofday(&tv_start, NULL);
        start_ms = (tv_start.tv_sec * 1000000 + tv_start.tv_usec) / 1000;
    }

    struct timeval tv_now;
    gettimeofday(&tv_now, NULL);
    uint64_t now_ms;
    now_ms = (tv_now.tv_sec * 1000000 + tv_now.tv_usec) / 1000;

    uint32_t time_ms = now_ms - start_ms;
    return time_ms;
}

4. 编译

4.1 makefile修改

CC设置为正点原子RK3568开发板的编译链,如:

CC = /opt/atk-dlrk3568-5_10_sdk-toolchain/bin/aarch64-buildroot-linux-gnu-gcc

4.2 make

make -j4

4.3 编译报错处理

通过make进行编译时会出现.h文件未发现及变量未定义等错误,其解决方法如下:

  1. drm.h、drm_fourcc.h、drm_mode.h未发现
    在这里插入图片描述
    由于drm.h、drm_fourcc.h、drm_mode.h存放于"/opt/atk-dlrk3568-5_10_sdk-toolchain/aarch64-buildroot-linux-gnu/sysroot/usr/include/drm" 路径中,但头文件引用时仅在“/opt/atk-dlrk3568-5_10_sdk-toolchain/aarch64-buildroot-linux-gnu/sysroot/usr/include”路径下进行查找,故未发现.h文件。因此,可直接修改.h文件代码,如下图所示:
    在这里插入图片描述
    或者,可将缺失文件直接拷贝至include路径下。

  2. undefined reference
    因编译时drm相关链接器不能自动加载,从而出现与drm相关的undefined reference报错,如下所示:

/opt/atk-dlrk3568-5_10_sdk-toolchain/bin/../lib/gcc/aarch64-buildroot-linux-gnu/10.4.0/../../../../aarch64-buildroot-linux-gnu/bin/ld: /home/royal/Program/lv_port_linux/lv_drivers/display/drm.o: in function `drm_allocate_dumb':
drm.c:(.text+0x78): undefined reference to `drmIoctl'
/opt/atk-dlrk3568-5_10_sdk-toolchain/bin/../lib/gcc/aarch64-buildroot-linux-gnu/10.4.0/../../../../aarch64-buildroot-linux-gnu/bin/ld: drm.c:(.text+0xac): undefined reference to `drmIoctl'
/opt/atk-dlrk3568-5_10_sdk-toolchain/bin/../lib/gcc/aarch64-buildroot-linux-gnu/10.4.0/../../../../aarch64-buildroot-linux-gnu/bin/ld: drm.c:(.text+0x11c): undefined reference to `drmModeAddFB2'
/opt/atk-dlrk3568-5_10_sdk-toolchain/bin/../lib/gcc/aarch64-buildroot-linux-gnu/10.4.0/../../../../aarch64-buildroot-linux-gnu/bin/ld: /home/royal/Program/lv_port_linux/lv_drivers/display/drm.o: in function `drm_add_crtc_property.isra.0':
drm.c:(.text+0x234): undefined reference to `drmModeAtomicAddProperty'
/opt/atk-dlrk3568-5_10_sdk-toolchain/bin/../lib/gcc/aarch64-buildroot-linux-gnu/10.4.0/../../../../aarch64-buildroot-linux-gnu/bin/ld: /home/royal/Program/lv_port_linux/lv_drivers/display/drm.o: in function `drm_add_plane_property.isra.0':
drm.c:(.text+0x324): undefined reference to `drmModeAtomicAddProperty'
......

若出现该报错,则在Makefile文件中添加LDFLAGS += -ldrm,实现的drm链接器加载。

LDFLAGS += -ldrm

5. 上传

打开cmd,使用adb push demo资源到指定路径XXX(自定义)。

adb push ./demo XXX

6. 运行

上传成功后,可通过adb shell进入adb界面,为demo赋可执行权限后,便可运行demo, 详细步骤如下:

adb shell
root@ATK-DLRK3568:/# chmod +x xxx/demo
root@ATK-DLRK3568:/# ./xxx/demo 

若demo正常运行,显示如下图所示:
在这里插入图片描述

注意:由于,当前开发板未关闭系统自带QT,所以需先kill系统U进程后,再运行demo。否则,demo显示内容不能持续显示,仅闪烁一次便被systemui抢占。
root@ATK-DLRK3568:/# killall systemui

7. 运行效果

显示效果如下图所示:
在这里插入图片描述

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐