跳到主要内容

RGB 屏幕

LuckFox Pico UltraLuckFox Pico Ultra W 现在支持RGB屏幕,采用并行的RGB LCD接口。图像数据以RGB666格式传输,每个像素占用 6 位。目前只适配 720x720480x480 分辨率。提供的镜像默认支持 720x720 分辨率。如果用户使用的是 480x480 分辨率的屏幕,可以在开发板开机后,按一下开发板的 BOOT按键进行分辨率切换。为了帮助大家的理解工作原理,本节会从应用层到驱动层进行介绍,由于屏幕种类繁多,其它分辨率屏幕适配还需要自行研究。

兼容平台

型号操作系统LF40-720720-ARKLF40-480480-ARK
Luckfox Pico UltraBuildroot/Ubuntu支持支持
Luckfox Pico Ultra WBuildroot/Ubuntu支持支持

注意:当前开发板Ubuntu22.04buildroot系统都适配了屏幕的驱动,但是lvgl示例程序当前仅支持buildroot系统。

1. 示例程序

  1. LVGL示例程序源码获取(在虚拟机或者Ubuntu主机上进行)。

    git clone https://github.com/luckfox-eng29/luckfox_lvgl.git
  2. 交叉编译示例程序。

    # 编译环境:WSL2 Ubuntu 22.02
    mkdir build
    cd build
    export LUCKFOX_SDK_PATH=<Luckfox Pico SDK 的绝对地址>
    cmake ..
    make -j
    • 最终编译生成的可执行文件: luckfox_lvgl_demo
  3. 硬件连接

    • Luckfox Pico Ultra:如果接入 LP40-720720-ARK 需要检查以下位置是否有焊接电阻,如果有,需将其拆除。LP40-480480-ARK 不需要检查此电阻是否有焊接。(从2024年7月5日之后发货的版本,此位置的电阻默认将不焊接)
    • 屏幕未连接FFC线,具体连接步骤如下:
      ①将转接板处的黑色卡扣向上撬起。
      ②将FFC排线的金属面朝下插入转接板。
      ③锁住卡扣。
      注意:屏幕不能正常显示(例如出现波纹),检查FFC线连接是否良好,可能需要重新插拔以确保接触良好。
    • 屏幕:Luckfox Pico Ultra 按图示接入屏幕

    注意: 接入屏幕时请断电操作,在上电前请再次检查是否接入正常,错误的连接会导致屏幕或者 Luckfox Pico Ultra 损坏。

    • 天线:LVGL 的示例程序可以进行 WIFI 连接(仅限 Luckfox Pico Ultra W),需要接入WIFI天线才能正常使用。

    • 喇叭:LVGL 的示例程序可以进行音乐播放,需要接入喇叭才能正常播放。

    • 可执行文件的上传运行

  4. 使用 adb 或者 scp 命令将文件上传到 Luckfox Pico Ultra 上,如果需要播放音乐请将准备播放的 .mp3 音频文件统一放置到 /music 文件夹中(如果没有该文件夹使用 mkdir 命令创建,缺少文件夹或者文件夹中没有 .mp3 文件都无法正常运行音乐播放功能)。由于开机默认运行的 RKIPC 程序会占用音频的使用,需要进行强制关闭后才可以执行测试程序。

    RkLunch-stop.sh
    chmod a+x ./luckfox_lvgl_demo
    ./luckfox_lvgl_demo
    • Luckfox Pico Ultra LVGL 示例程序主界面。

2. MIPI DPI 接口

RGB 接口也被称为 DPI(Display Pixel Interface) 接口,采用普通的同步、时钟、信号线来传输特定数据,采用 IIC 等控制线完成命令控制,DPI接口信号线:

  1. DPIVSYNC (Vertical Sync): 垂直同步信号,用于指示一帧图像的开始。
  2. DPIHSYNC (Horizontal Sync): 水平同步信号,用于指示一行像素的开始。
  3. DPIDE (Data Enable): 数据有效信号,用于指示当前传输的数据是有效的像素数据。
  4. DPICK (Clock): 像素时钟信号,用于同步数据传输。
  5. 数据线: 多条并行数据线(如DPI_DATA0, DPI_DATA1, ...),用于传输像素数据。

3. Rockchip 平台显示子系统(DSS)

显示子系统是Rockchip平台显示输出相关软硬件系统的统称,linux内核采用component框架来构建显示子系统,一个显示子系统由显示处理器(vopvideo output processor)、接口控制器(mipilvdshdmiedpdprgbBT1120BT656I8080MCU 显示接口)等)、液晶背光,电源等多个独立的功能模块构成。将在内存中的图像数据,转化为电信号送到显示设备称为显示控制器,比如早期的LCDC;后面进行了拓展,可以处理一些简单的图像,比如缩放、旋转、合成等,如瑞芯微的vop和博通的VideoCore都称为显示处理器。RV1106 采用的VOP1.0 ,整个显示系统的硬件框架如下图所示:

4. FBDEV 介绍

Linux 内核中常用的两类图形显示设备驱动框架分别是 DRM(Direct Rendering Manager)和 FBDEV(Framebuffer Device)。在 Framebuffer 驱动框架下,用户可以通过 /dev/fbX 接口直接操作显示设备的显存,进行标准文件操作(如 read, write, ioctl)。用户空间程序可以通过这些设备节点和 ioctl 调用来控制帧缓冲设备。Framebuffer 提供基本的 2D 图形操作,如点、线、矩形的绘制,支持多种像素格式和分辨率。缺点是它不支持现代图形硬件的高级功能,如硬件加速和 3D 渲染。

5. DRM 介绍

DRM 全称是 Direct Rendering Manager,进行显示输出管理、buffer 分配、帧缓冲。对应的 userspace 库为 libdrm,libdrm 库提供 了一系列友好的控制封装,使用户可以方便的进行显示的控制和 buffer 申请。DRM 的设备节点为 "/dev/dri/cardX", X 为 0-15 的数 值,默认使用的是 /dev/dri/card0。 Rockchip 平台从 Linux 4.4 内核开始,显示驱动全部切到 DRM 显示框架。

5.1 DRM 与 framebuffer 的区别

下图是 FBDEV 和 DRM 连接到设备端最终显示过程对比:

6. DRM 基本概念

为了方便管理显示通路上的各种硬件模块,DRM 定义了以下几个概念:

基本概念说明
CRTC显示控制器;RGB timing的产生,以及显示数据的更新,都需要访问Dislay Controller硬件寄存器,因此放在Display Controller驱动中
在Rockchip平台里对应SoC内部的vop模块
Plane图层,在 rockchip 平台是 SOC 内部 VOP(LCDC)模块 win 图层的抽象
Encoder输出转换器,指 RGB、LVDS、DSI、eDP、DP、HDMI、CVBS、VGA 等显示接口
Connector连接器,指 encoder 和 panel 之间交互的接口部分
Bridge桥接设备,一般用于注册 encoder 后面另外再接的转换芯片,如 DSI2HDMI 转换芯片
Panel泛指屏,各种 LCD 显示设备的抽象
GEMDRM 下 buffer 管理和分配,类似 ION、DMA BUFFER

7. DRM 框架介绍

DRM 驱动和 libdrm 的交互过程:

7.1 Libdrm

在 DRM 框架中,libdrm(Direct Rendering Manager library)是一个用户空间库。,提供了DRM驱动的用户空间接口;对底层接口进行封装,向上层应用程序提供通用的API接口,本质上是对各种ioctl接口进行封装。

7.2 KMS

KMS(Kernel Mode Setting)使内核直接管理显示模式和分辨率,提高了系统的稳定性和性能。KMS 包含 CRTC(Cathode Ray Tube Controller),用于控制显示扫描;Plane,用于管理图形数据层;Encoder,将图形数据转换为适当的输出信号;以及 Connector,连接显示设备,如显示器或电视。

7.3 GEM

GEM(Graphics Execution Manager)负责显存的分配和管理,提供高效的显存操作机制。它与 DRM 的其他组件,如 Plane、CRTC 和 Panel 协同工作,以确保图形数据在显存中的高效传输和渲染,支持硬件加速和现代图形硬件的高级功能。

7.4 drm_panel

drm_panel 是 DRM(Direct Rendering Manager)框架中的一个重要概念,尽管它不像 drm_crtcdrm_connectordrm_plane 等直接被认为是对象,但它的存在降低了LCD驱动与encoder驱动之间的耦合度。drm_panel它是一堆回调函数的集合,这些回调函数允许显示驱动程序和其他部分(如 encoder 驱动程序)与显示面板进行交互。

8. 驱动模块路径

linux内核将DRM驱动相关的代码都放在drivers/gpu/drm目录下,驱动部分内容作为了解即可。

驱动文件位置
coredrivers/gpu/drm/rockchip/rockchip_drm_drv.c
framebufferdrivers/gpu/drm/rockchip/rockchip_drm_fb.c
vopdrivers/gpu/drm/rockchip/rockchip_drm_vop.c
drivers/gpu/drm/rockchip/rockchip_vop_reg.c
drivers/gpu/drm/rockchip/rockchip_drm_vop2.c<br/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
rgbdrivers/gpu/drm/rockchip/rockchip_rgb.c
paneldrivers/gpu/drm/panel/panel-simple.c
drivers/gpu/drm/drm_panel.c

9. DRM 驱动入口

  1. 平台驱动(Platform Driver) 和设备的匹配,这里是直接比较驱动和设备的字段,看看是否相同。通过 compatible 属性,内核会将 simple-panel 驱动与设备树中的 panel 节点进行匹配。

    static struct platform_driver panel_simple_platform_driver = {
    .driver = {
    .name = "panel-simple",
    .of_match_table = platform_of_match,
    },
    .probe = panel_simple_platform_probe,
    .remove = panel_simple_platform_remove,
    .shutdown = panel_simple_platform_shutdown,
    };
  2. 驱动的 probe 函数会检查 display-timings 节点,并解析其中的时序参数。根据解析得到的时序参数,驱动会配置显示控制器,以确保面板能够正确显示。

    static int panel_simple_of_get_desc_data(struct device *dev,
    struct panel_desc *desc)
    {
    struct device_node *np = dev->of_node;
    u32 bus_flags;
    const void *data;
    int len;
    int err;

    if (of_child_node_is_present(np, "display-timings")) {
    struct drm_display_mode *mode;

    mode = devm_kzalloc(dev, sizeof(*mode), GFP_KERNEL);
    if (!mode)
    return -ENOMEM;

    if (!of_get_drm_display_mode(np, mode, &bus_flags,
    OF_USE_NATIVE_MODE)) {
    desc->modes = mode;
    desc->num_modes = 1;
    desc->bus_flags = bus_flags;
    }
  3. 设备树中定义的面板节点会被panel-simple驱动探测到,panel_simple_platform_probe函数会读取设备树中的面板描述信息,并通过panel_simple_probe 函数进行面板初始化和注册。

    static int panel_simple_platform_probe(struct platform_device *pdev)
    {
    struct device *dev = &pdev->dev;
    const struct of_device_id *id;
    const struct panel_desc *desc;
    struct panel_desc *d;
    int err;

    id = of_match_node(platform_of_match, pdev->dev.of_node);
    if (!id)
    return -ENODEV;

    if (!id->data) {
    d = devm_kzalloc(dev, sizeof(*d), GFP_KERNEL);
    if (!d)
    return -ENOMEM;

    err = panel_simple_of_get_desc_data(dev, d);
    if (err) {
    dev_err(dev, "failed to get desc data: %d\n", err);
    return err;
    }
    }

    desc = id->data ? id->data : d;

    return panel_simple_probe(&pdev->dev, desc);
    }
  4. 注册过程中,drm_panel_initdrm_panel_add函数会将面板初始化并注册到 DRM 框架中,使其成为 DRM 子系统的一部分,供其他 DRM 组件使用。

    void drm_panel_init(struct drm_panel *panel, struct device *dev,
    const struct drm_panel_funcs *funcs, int connector_type)
    {
    INIT_LIST_HEAD(&panel->list);
    panel->dev = dev;
    panel->funcs = funcs;
    panel->connector_type = connector_type;
    }
    EXPORT_SYMBOL(drm_panel_init);

    /**
    * drm_panel_add - add a panel to the global registry
    * @panel: panel to add
    *
    * Add a panel to the global registry so that it can be looked up by display
    * drivers.
    */
    void drm_panel_add(struct drm_panel *panel)
    {
    mutex_lock(&panel_lock);
    list_add_tail(&panel->list, &panel_list);
    mutex_unlock(&panel_lock);
    }
    EXPORT_SYMBOL(drm_panel_add);
  5. DRM 驱动模块入口函数为rockchip_drm_init,位于drivers/gpu/drm/rockchip/rockchip_drm_drv.c

    #define ADD_ROCKCHIP_SUB_DRIVER(drv, cond) { \
    if (IS_ENABLED(cond) && \
    !WARN_ON(num_rockchip_sub_drivers >= MAX_ROCKCHIP_SUB_DRIVERS)) \
    rockchip_sub_drivers[num_rockchip_sub_drivers++] = &drv; \
    }

    static int __init rockchip_drm_init(void)
    {
    int ret;

    num_rockchip_sub_drivers = 0;
    #if IS_ENABLED(CONFIG_DRM_ROCKCHIP_VVOP)
    ADD_ROCKCHIP_SUB_DRIVER(vvop_platform_driver, CONFIG_DRM_ROCKCHIP_VVOP);
    #else
    ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_ROCKCHIP_VOP);
    ...
    ADD_ROCKCHIP_SUB_DRIVER(rockchip_rgb_driver, CONFIG_ROCKCHIP_RGB);
    ...

    #endif
    ret = platform_register_drivers(rockchip_sub_drivers,
    num_rockchip_sub_drivers);
    if (ret)
    return ret;

    ret = platform_driver_register(&rockchip_drm_platform_driver);
    if (ret)
    goto err_unreg_drivers;

    rockchip_gem_get_ddr_info();

    return 0;

    err_unreg_drivers:
    platform_unregister_drivers(rockchip_sub_drivers,
    num_rockchip_sub_drivers);
    return ret;
    }
    • 在前面的内核配置中我们已经打开CONFIG_ROCKCHIP_VOPCONFIG_ROCKCHIP_RGB,所以此步将vop_platform_driverrockchip_rgb_driver驱动添加到数组rockchip_sub_drivers
    • 通过platform_register_drivers注册多个驱动和注册rockchip_drm_platform_driver
  6. 平台驱动(Platform Driver) 和设备的匹配,这里是直接比较驱动和设备的字段,看看是否相同。rockchip-drm平台驱动rockchip-drm 是一个针对 Rockchip 芯片的 DRM 驱动,它主要用于管理和控制显示子系统。

    static struct platform_driver rockchip_drm_platform_driver = {
    .probe = rockchip_drm_platform_probe,
    .remove = rockchip_drm_platform_remove,
    .shutdown = rockchip_drm_platform_shutdown,
    .driver = {
    .name = "rockchip-drm", //此字段为device和driver匹配的最后一种方式
    .of_match_table = rockchip_drm_dt_ids,
    .pm = &rockchip_drm_pm_ops,
    },
    };
  7. of_match_table用于设备树匹配,匹配设备树中compatible = "rockchip,display-subsystem"的设备节点:

    static const struct of_device_id rockchip_drm_dt_ids[] = {
    { .compatible = "rockchip,display-subsystem", },
    { /* sentinel */ },
    };
  8. 在第二步内核中有platform设备和platform驱动匹配,会调用到platform_driver里的成员.probe,在这里就是rockchip_drm_platform_probe函数:

    static int rockchip_drm_platform_probe(struct platform_device *pdev)
    {
    struct device *dev = &pdev->dev;
    struct component_match *match = NULL;
    int ret;

    ret = rockchip_drm_platform_of_probe(dev);
    #if !IS_ENABLED(CONFIG_DRM_ROCKCHIP_VVOP)
    if (ret)
    return ret;
    #endif

    match = rockchip_drm_match_add(dev);
    if (IS_ERR(match))
    return PTR_ERR(match);

    ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(64));
    if (ret)
    goto err;

    ret = component_master_add_with_match(dev, &rockchip_drm_ops, match);
    if (ret < 0)
    goto err;

    return 0;
    err:
    rockchip_drm_match_remove(dev);

    return ret;
    }
    • ret = rockchip_drm_platform_of_probe(dev);: 校验display-subsystem设备节点的属性ports是否有效
    • match = rockchip_drm_match_add(dev);:构建一个带release函数的component_match
    • ret = component_master_add_with_match(dev, &rockchip_drm_ops, match);:向系统注册一个aggregate_device,触发执行rockchip_drm_ops.bind,即rockchip_drm_bind,该函数用于绑定设备并初始化DRM驱动

总结:

  1. 设备树匹配:设备树中定义的面板节点通过设备树匹配机制与 panel-simple 驱动关联。内核启动时,rockchip-drm 平台驱动也会匹配设备树节点。驱动查找并解析设备树中的 portsiommus 节点,以获取显示管道和内存管理单元的信息。
  2. 面板驱动初始化panel_simple_platform_probe 函数读取设备树中的面板描述信息,并通过 panel_simple_probe 函数进行面板初始化和注册。在此过程中,调用 drm_panel_initdrm_panel_add 函数将面板初始化并注册到 DRM 框架中,使其成为 DRM 子系统的一部分,供其他 DRM 组件使用。
  3. 注册组件rockchip-drm 使用 component_master_add_with_match 函数将其注册到组件框架中。通过设置 rockchip_drm_ops,定义了 bindunbind 操作,这些操作将在组件初始化和注销时调用。
  4. 添加子组件:各个子组件(例如 VOP、HDMI、MIPI DSI 等)使用 component_add 函数添加到组件框架中。每个子组件都有对应的 component_ops 结构体,定义其自身的 bindunbind 操作。
  5. 绑定组件:当 master 组件(即 rockchip-drm)匹配到所有子组件后,会调用其 bind 回调函数。在 bind 回调函数中,执行各个子组件的初始化和配置。
  6. 注册到 DRM 核心rockchip-drm 驱动在内核模块加载时通过 drm_dev_register 函数注册 DRM 设备。在此过程中,drm_dev_register 会调用 drm_minor_register 注册字符设备。drm_minor_register 函数负责创建字符设备并添加到 /dev/dri 目录下,最终创建设备节点,如 /dev/dri/card0

想了解更多具体内容,需自己进入源码目录(drivers/gpu/drm)阅读理解。

10. RGB 屏幕系统配置

10.1 内核配置

Luckfox Pico Ultra 驱动 RGB 需要在内核设置中打开 VOP 驱动支持和 RGB 驱动支持(默认打开)。

  1. 在 luckfox-pico SDk 根目录下打开 kernel 的 menuconfig 配置页面。

    # Buildroot 系统
    ./build.sh kernelconfig
    # Ubuntu 系统
    sudo ./build.sh kernelconfig
  2. 输入 “/” 搜索 CONFIG_DRM_ROCKCHIP 选择第一项。

  3. 配置 DRM Support for Rockchip ,输入 “y” 打开 Rockchip VOP driverRockchip RGB support

    Device Drivers --->
    Graphics support --->
    <*> Direct Rendering Manager (XFree86 4.1.0 and higher DRI support) --->
    <*> DRM Support for Rockchip (DRM_ROCKCHIP [=y])
    [ ] Support 3D cubic LUT
    [ ] Rockchip DRM debug
    [ ] Rockchip DRM direct show
    [*] Rockchip VOP driver
    [ ] Rockchip VOP2 driver
    [ ] Rockchip specific extensions for Analogix DP driver
    [ ] Rockchip cdn DP
    [ ] Rockchip TVE support
    [ ] Rockchip specific extensions for Synopsys DW HDMI
    [ ] Rockchip specific extensions for Synopsys DW MIPI DSI
    [ ] Rockchip specific extensions for Synopsys DW DPTX
    [ ] Rockchip specific extensions for Innosilicon HDMI
    [ ] Rockchip LVDS support
    [*] Rockchip RGB support
    [ ] Rockchip specific extensions for RK3066 HDMI
    [ ] Rockchip Virtual connector driver for HDMI/DP/DSI
    [ ] Rockchip virtual VOP drm driver< > Synopsis Designware HDCP2 interface
  • 在 luckfox-pico Sdk 根目录下执行命令编译生成 boot.img

    # Buildroot 系统
    ./build.sh kernel
    # Ubuntu 系统
    sudo ./build.sh kernel

    注意: 建议在修改好 RGB 屏幕和电容触摸屏的设备树后再编译烧录 boot.img

10.2 设备树设置

  1. RGB 和 VOP 配置

    在 Luckfox Pico Ultra 上与 RGB 显示的相关设备树设置已经在 <Luckfox Pico Sdk Path>/sysdrv/source/kernel/arch/arm/boot/dts/rv1106-luckfox-pico-ultra-ipc.dtsi 中默认打开。

    &display_subsystem {
    status = "okay";
    logo-memory-region = <&drm_logo>;
    };

    &rgb {
    status = "okay";
    pinctrl-names = "default";
    pinctrl-0 = <&lcd_pins>;

    ports {
    rgb_out: port@1 {
    reg = <1>;
    #address-cells = <1>;
    #size-cells = <0>;

    rgb_out_panel: endpoint@0 {
    reg = <0>;
    remote-endpoint = <&panel_in_rgb>;
    };
    };
    };
    };

    &rgb_in_vop {
    status = "okay";
    };

    &route_rgb {
    status = "okay";
    };

    &vop {
    status = "okay";
    };

    注意: 如果需要取消 RGB 屏幕的使用,可以将 &rgb 节点的 status 修改为 “disabled”,防止打算使用的外设引脚被复用为 lcd 引脚。在使能 RGB 屏幕时,请不要将相关引脚复用为其它功能或接入其它外设。

  2. CMA 配置

    使用 LF40-720720-ARK 时由于默认分配的 CMA 大小不够,需要额外申请 10MB 内存作为 CMA 才能正常显示图像。CMA 是从内存中申请的,会导致可使用的内存大小减少,在不需要使用 LF40-720720-ARK 时可以将 <luckfox-pico SDK>/ sysdrv/source/kernel/arch/arm/boot/dts/rv1106-luckfox-pico-ultra-ipc.dtsi 下的 reserved-memory/linux,cma 节点注释掉,释放内存资源。

        reserved-memory {
    #address-cells = <1>;
    #size-cells = <1>;
    ranges;
    drm_logo: drm-logo@00000000 {
    compatible = "rockchip,drm-logo";
    reg = <0x0 0x0>;
    };
    //linux,cma {
    // compatible = "shared-dma-pool";
    // inactive;
    // reusable;
    // size = <0xA00000>;
    // linux,cma-default;
    //};
    };
  3. panel 配置 除了默认的设备树配置,需要额外配置主要是屏幕的 panel 节点。

    在最新的 luckfox-pico SDK 中,最上层的 dts 文件已经软链接到 luckfox-pico SDK 根目录下的 config/dts_config 中,只需要对其进行修改就能覆盖 dtsi 中的设置,根据型号在 config/dts_config 中添加相应内容就可以完成设备树的配置。

  • LF40-720720-ARK 设备树配置

    /**********RGB**********/
    &panel {
    status = "okay";
    reset {
    status = "okay";
    };
    enable {
    status = "disabled";
    };
    display-timings {
    timing0: timing0 {
    clock-frequency = <30000000>;
    hactive = <720>;
    vactive = <720>;
    hback-porch = <44>;
    hfront-porch = <46>;
    vback-porch = <18>;
    vfront-porch = <16>;
    hsync-len = <2>;
    vsync-len = <2>;
    hsync-active = <0>;
    vsync-active = <0>;
    de-active = <0>;
    pixelclk-active = <0>;
    };
    };
    };
  • LF40-480480-ARK 设备树配置

    /**********RGB**********/
    &panel {
    status = "okay";
    reset {
    status = "okay";
    };
    enable {
    status = "disabled";
    };
    display-timings {
    timing0: timing0 {
    clock-frequency = <16500000>;
    hactive = <480>;
    vactive = <480>;
    hback-porch = <10>;
    hfront-porch = <50>;
    vback-porch = <8>;
    vfront-porch = <8>;
    hsync-len = <4>;
    vsync-len = <10>;
    hsync-active = <0>;
    vsync-active = <0>;
    de-active = <0>;
    pixelclk-active = <1>;
    };
    };
    };

10.2 DRM 测试

RGB 屏幕可以使用 Framebuffer 框架或 DRM 框架进行控制。使用 buildroot 系统自带的 modetest 工具可以获取 DRM 的 Connectors IDCRTCS ID 用于显示测试。

  1. Luckfox Pico Ultra 使用 Ubuntu 系统需要安装 modetest 工具(buildroot系统默认已安装)

    # 确保 Luckfox Pico Ultra 成功连接网络
    sudo apt-get update
    sudo apt-get install libdrm-dev
    sudo apt-get install libdrm-tests
  2. modetest 获取 Connector ID

  3. modetest 获取 CRTCS ID

  4. 执行测试程序显示色块

    modetest -M rockchip -s <Connector ID>@<CRTCS ID>:<显示分辨率>
  5. 示例:

    • LF40-480480-ARK

      modetest -M rockchip -s 70@66:720x720
    • LF40-720720-ARK

      modetest -M rockchip -s 70@66:480x480

11. 电容触摸屏系统配置

LF40-720720-ARKLF40-480480-ARK 都贴合了GT911电容触摸屏,使用 I2C 进行控制。

11.1 内核配置

Luckfox Pico Ultra 在控制触摸屏时会将 I2C 连接的 GT911 触摸屏设置为 input 设备,需要在内核中打开对应的驱动。

  1. 在 luckfox-pico Sdk 根目录下执行命令进入 kernel 的 menuconfig 界面。

    # Buildroot 系统
    ./build.sh kernelconfig
    # Ubuntu 系统
    sudo ./build.sh kernelconfig
  2. 使用 “/” 进行搜索, 搜索 TOUCHSCREEN_GOODIX 选择第一项

  3. 选中 Goodix I2C touchscreen 按下 “y” 键选中后保存退出

  4. 在 luckfox-pico Sdk 根目录下执行命令编译生成 boot.img

    # Buildroot 系统
    ./build.sh kernel
    # Ubuntu 系统
    sudo ./build.sh kernel

    注意: 建议在修改好 RGB 屏幕和电容触摸屏的设备树后再编译烧录 boot.img

11.2 设备树设置

GT911 触摸会根据上电时序配置不同的 I2C 地址,驱动加载成功后会与 GT911 通讯获取到电容触摸屏的分辨率数据,所以 LF40-720720-ARKLF40-480480-ARK 的设备树配置一致。

  • GT911 设备树配置

    /**********TouchScreen**********/
    &i2c3 {
    status="okay";
    clock-frequency = <100000>;
    pinctrl-names = "default";
    pinctrl-0 = <&i2c3m2_xfer &tp_rst &tp_irq>;
    GT911:touchscreen {
    compatible = "goodix,gt911";
    reg = <0x14>;

    interrupt-parent = <&gpio0>;
    interrupts = <RK_PA3 IRQ_TYPE_EDGE_FALLING>;

    reset-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>;

    };
    };

    &pinctrl {
    Touchscreen{
    tp_rst:tp-rst {
    rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>;
    };

    tp_irq:tp-irq {
    rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>;
    };
    };

    };

    注意: GT911 触摸屏会占用 I2C3M2,请确保 I2C3 的其它组没有被使用。

11.3 触摸屏测试

11.3.1 i2c 测试

如果上电时序正确,那么 GT911 触摸屏会在 I2C3 的 0x14 地址上被识别到,GT911 的驱动会占用该地址。

  1. 使用 i2cdetect 命令查看 I2C3 的设备挂载情况。

    i2cdetect -y 3
  2. 可以观察到 I2C3 的 0x14 地址会被标记 "UU"。

    注意: 如果 I2C3 的 0x14 地址没有被识别到,可能是上电时序错误或接触不良,需要检查 FPC 软排线是否安装稳定。

11.3.2 hexdump 测试

GT911 触摸屏驱动在加载过程中会在 /dev/input 下创建 event 节点用于传递触摸信息,在 Luckfox Pico Ultra 上没有添加其它 input 设备的话, GT911 触摸屏对应节点通常是 /dev/input/event0

  1. Luckfox Pico Ultra 使用 ubuntu 系统需要安装 hexdump 工具(buildroot系统默认已安装)

    # 确保 Luckfox Pico Ultra 成功连接网络
    sudo apt-get update
    sudo apt-get install bsdmainutils
  2. 使用 hexdump 命令获取 GT911 传输信息。

    hexdump /dev/input/event0
  3. 用手指触摸屏幕触发中断,此时打印的信息是 GT911 传递到 input 子系统的初始信息,需要通过整理才能获取到实际的坐标值。

    注意: Luckfox Pico Ultra 上的 adc-key (对应 BOOT 按键) 也被注册为 event 节点,如果 GT911 触摸屏驱动没有成功加载, 那么 /dev/input/event0 节点对应的是 adc-key ; 如果有其它 input 设备的加载顺序较早,那么 GT911 触摸屏可能被加载到 /dev/input/event1 或其它节点上。

11.3.3 evtest 测试

如果需要观察触摸实际坐标数据和 input 设备更详细的信息可以通过在 buildroot 中添加 evtest 工具来进行测试,方便在有多个 input 设备时进行区分。

  1. Luckfox Pico Ultra 系统自带 evtest 工具,可以跳过 2 ~ 6 步。

  2. 在 luckfox-pico SDK 根目录下执行命令进入 buildroot 的 menuconfig 界面。

    ./build.sh buildrootconfig 
  3. 使用 “/” 进行搜索, 搜索 BR2_PACKAGE_EVTEST 选择第一项

  4. 使用 “y” 将 evtest 打开后保存退出。

  5. 执行命令重新编译生成 rootfs.img

    # Buildroot 系统
    ./build.sh rootfs
    ./build.sh firmware
  6. 将新生成的 rootfs.img 烧写入 Luckfox Pico Ultra 中就可以使用 evtest 来测试 input 设备。

  7. 其中的 Goodix Capacitive TouchScreen 对应的就是 GT911 触摸屏,选中 0 回车就可以看到 GT911 触摸屏设备的相关信息,触摸屏幕就可以观察到触发的事件信息和坐标数据( ABS_X 和 ABS_Y )。