RK3288设备树介绍和配置

在嵌入式Linux开发中,设备树(Device Tree)是连接硬件与内核的关键桥梁,尤其对于瑞芯微RK3288这类高性能ARM芯片而言,熟练掌握设备树的配置与修改,是实现硬件驱动适配、系统定制的核心能力。本文将从设备树的基本概念出发,聚焦RK3288平台,详解其设备树的结构、核心作用、常见修改场景及编译更新流程,帮助嵌入式开发者快速上手。

一、先搞懂:设备树是什么?

设备树(Device Tree,简称DTS)是一种采用ASCII文本格式描述硬件的数据结构,起源于OpenFirmware(OF)规范。在传统的Linux 2.6内核中,ARM架构的硬件细节(如CPU数量、内存地址、外设接口等)大多硬编码在内核源码的arch/arm/plat-xxx和arch/arm/mach-xxx目录下,导致内核冗余度高、适配不同开发板时需要大量修改内核代码。

引入设备树后,这一问题得到了根本性解决:硬件细节不再嵌入内核,而是通过独立的设备树文件描述,Bootloader启动时会将设备树传递给内核,内核根据设备树信息自动识别硬件、匹配驱动,实现了"内核与硬件解耦"。对于RK3288平台而言,设备树就是其硬件的"说明书",内核通过这份"说明书"就能清楚了解开发板的硬件配置。

二、RK3288设备树的核心文件与结构

RK3288的设备树文件主要位于Linux内核源码的arch/arm/boot/dts/目录下,核心文件分为两类:.dtsi(设备树头文件)和.dts(设备树源文件),二者的关系类似C语言的头文件与源文件。

  1. 核心文件分类
  • rk3288.dtsi:RK3288芯片级的通用设备树文件,包含芯片核心硬件的描述(如CPU、中断控制器、时钟控制器、GPIO控制器等),是所有基于RK3288的开发板设备树的基础,多个开发板可共用这份文件,避免重复编码。

  • rk3288-xxx.dts:针对具体RK3288开发板的设备树文件(如rk3288-firefly.dts对应萤火虫RK3288开发板),主要描述开发板级的硬件配置(如外设的引脚连接、外设型号等),通过#include "rk3288.dtsi"引入芯片级通用配置。

  • 相关头文件:位于dt-bindings/目录下,如gpio/gpio.h(GPIO相关宏定义)、clock/rk3288-cru.h(时钟相关宏定义)等,提供设备树中常用的宏定义,简化配置编写。

  1. 核心结构解析

RK3288设备树采用"节点-属性"的树形结构,所有节点都以根节点/为起点,子节点嵌套在父节点中,属性则用于描述节点的具体信息(如地址、兼容型号、中断信息等)。以下是核心结构示例及说明:

复制代码
// 1. 头文件引入
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include "rk3288.dtsi"

// 2. 根节点
/ {
    #address-cells = <2>;  // 子节点地址字段的长度(2个32位值)
    #size-cells = <2>;     // 子节点地址长度字段的长度(2个32位值)
    compatible = "rockchip,rk3288";  // 匹配内核中的机器描述,用于内核识别开发板
    interrupt-parent = <&gic>;  // 默认中断控制器(引用gic节点)
};

// 3. 别名节点(简化节点引用)
aliases {
    serial0 = <&uart0>;  // 将uart0节点别名设为serial0,后续可通过serial0快速引用
    i2c0 = <&i2c0>;
    spi0 = <&spi0>;
};

// 4. 子节点示例(以UART0为例)
uart0: serial@ff690000 {
    compatible = "rockchip,rk3288-uart";  // 兼容型号,用于匹配UART驱动
    reg = <0x0 0xff690000 0x0 0x1000>;   // 寄存器地址与长度
    interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;  // 中断信息
    clocks = <&cru UART0_CLK>;  // 时钟源
    status = "okay";  // 使能该节点("disabled"为禁用)
};

关键属性说明:

  • compatible:最核心的属性,用于"驱动匹配",内核通过该属性查找对应的驱动程序(如UART节点的"rockchip,rk3288-uart"会匹配RK3288的UART驱动)。

  • reg:描述设备寄存器的物理地址和长度,内核通过该属性映射寄存器地址,实现对硬件的操作。

  • interrupts:中断信息,格式由中断控制器决定(RK3288使用GIC中断控制器,格式为<中断类型 中断号 触发方式>)。

  • status:控制节点启用/禁用,"okay"表示启用该外设,"disabled"表示禁用。

三、RK3288设备树的核心作用

对于RK3288开发而言,设备树的核心作用是"描述硬件、衔接内核与驱动",具体体现在以下3个场景:

  1. 内核识别硬件配置

设备树向内核传递的核心硬件信息包括:CPU数量与型号(RK3288为4核Cortex-A12)、内存基地址与大小(如2GB内存的地址范围)、外设的寄存器地址、中断号、GPIO引脚分配等。内核启动时解析设备树,自动识别这些硬件信息,无需硬编码。

  1. 驱动匹配与外设启用

内核中的驱动程序会预先定义支持的compatible属性值,当设备树节点的compatible属性与驱动的属性匹配时,驱动会自动加载并绑定到该设备。例如,若要启用RK3288的SPI0外设,只需在设备树中设置SPI0节点的status = "okay",并配置正确的compatible属性,内核就能自动匹配SPI驱动。

  1. 硬件配置定制化

不同RK3288开发板的外设配置可能不同(如A开发板使用SPI0连接TFT屏幕,B开发板使用SPI1连接温湿度传感器),通过修改设备树的节点配置(如引脚分配、compatible属性、时钟频率等),即可实现不同硬件配置的定制化,无需修改内核代码。例如,在RK3288上添加ILI9341 SPI屏幕时,只需在设备树的SPI节点下添加ILI9341的子节点,配置引脚、时钟频率等信息即可。

四、RK3288设备树的常见修改场景与示例

在RK3288开发中,设备树的修改是高频操作,以下是2个最常见的修改场景及示例:

场景1:启用/禁用外设(以UART0为例)

若开发板需要使用UART0外设,只需找到UART0节点,将status属性设为"okay";若不需要使用,设为"disabled"即可:

复制代码
uart0: serial@ff690000 {
    compatible = "rockchip,rk3288-uart";
    reg = <0x0 0xff690000 0x0 0x1000>;
    interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
    clocks = <&cru UART0_CLK>;
    status = "okay";  // 启用UART0(禁用改为"disabled")
};

场景2:添加SPI外设(以ILI9341 TFT屏幕为例)

若要在RK3288的SPI0上连接ILI9341 TFT屏幕,需在SPI0节点下添加ILI9341的子节点,配置引脚、时钟频率等信息:

复制代码
&spi0 {  // 引用SPI0节点(通过别名或节点路径)
    status = "okay";  // 启用SPI0
    
    ili9341@0 {  // ILI9341子节点,@0表示SPI从设备地址为0
        compatible = "ilitek,ili9341";  // 匹配ILI9341驱动
        reg = <0>;
        spi-max-frequency = <50000000>;  // SPI最大频率50MHz
        rotate = <270>;  // 屏幕旋转270度
        bgr;  // 颜色格式为BGR
        reset-gpios = <&gpio7 3 GPIO_ACTIVE_LOW>;  // 复位引脚(GPIO7_3,低电平有效)
        dc-gpios = <&gpio7 9 GPIO_ACTIVE_LOW>;    // 数据/命令引脚(GPIO7_9,低电平有效)
        status = "okay";
    };
};

五、RK3288设备树的编译与更新流程

修改设备树后,无需重新编译整个内核,只需单独编译设备树,生成二进制文件.dtb,再更新到开发板的boot分区即可生效。具体步骤如下:

  1. 编译设备树

进入Linux内核源码根目录,执行以下命令编译设备树(需指定架构和交叉编译工具链):

复制代码
# 编译所有RK3288相关的设备树(生成.dtb文件)
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- dtbs
# 或单独编译指定开发板的设备树(如rk3288-firefly.dts)
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- rk3288-firefly.dtb

编译完成后,生成的.dtb文件位于arch/arm/boot/dts/目录下(如rk3288-firefly.dtb)。

  1. 更新设备树到开发板

有两种常用方式更新设备树,可根据开发场景选择:

方式1:直接挂载boot分区替换(推荐,无需重新烧录镜像)

RK3288的boot分区通常为FAT32格式,可直接在开发板上挂载后替换.dtb文件:

复制代码
# 1. 查看boot分区设备名(通常为/dev/mmcblk2p4,以实际为准)
fdisk -l
# 2. 创建挂载点并挂载boot分区
mkdir -p /mnt/boot
mount /dev/mmcblk2p4 /mnt/boot
# 3. 将新编译的.dtb文件复制到boot分区(替换原有文件)
cp arch/arm/boot/dts/rk3288-firefly.dtb /mnt/boot/
# 4. 卸载boot分区
umount /mnt/boot
# 5. 重启开发板,新设备树生效
reboot

方式2:重新打包boot.img烧录

若开发板的boot分区无法直接挂载,可将新的.dtb文件与内核镜像(zImage)重新打包为boot.img,再通过瑞芯微烧录工具(如RKDevTool、upgrade_tool)单独烧录boot分区:

复制代码
# 以瑞芯微rockdev目录为例,执行打包脚本
cd rockdev
./mkbootimg.sh  # 自动整合zImage和新的.dtb文件生成boot.img

注意:单独烧录boot.img不会影响rootfs分区(如/etc目录下的配置文件),安全性高。

六、常见问题与注意事项

  • 修改后设备树不生效? 检查status属性是否设为"okay"、compatible属性是否正确、.dtb文件是否正确替换到boot分区,可通过dmesg | grep dtb查看设备树加载日志排查问题。

  • 编译设备树报错"未定义的宏"? 检查是否引入了对应的头文件(如GPIO宏需引入dt-bindings/gpio/gpio.h)。

  • 不要直接修改rk3288.dtsi:rk3288.dtsi是芯片级通用文件,修改后会影响所有基于RK3288的开发板,开发板级的修改应在对应的rk3288-xxx.dts文件中进行。

  • 参考官方文档:设备树节点和属性的配置需遵循规范,可参考内核源码的Documentation/devicetree/bindings/目录下的文档(如UART对应serial/rockchip-uart.txt)。

七、总结

RK3288设备树是描述硬件的"结构化说明书",其核心价值在于实现"内核与硬件解耦",简化开发板适配流程。对于嵌入式开发者而言,掌握设备树的结构、核心属性及修改方法,是基于RK3288进行硬件定制和驱动开发的基础。

相关推荐
末日汐2 小时前
Linux进程信号
linux·运维·服务器
无垠的广袤2 小时前
【工业树莓派 CM0 NANO 单板计算机】YOLO26 部署方案
linux·python·opencv·yolo·树莓派·目标识别
皮蛋sol周3 小时前
嵌入式学习数据结构(二)双向链表 内核链表
linux·数据结构·学习·嵌入式·arm·双向链表
Sleepy MargulisItG3 小时前
【Linux网络编程】网络层协议:IP
linux·网络·tcp/ip
叠叠乐3 小时前
移动家庭云电脑linux docker 容器登陆移动家庭云电脑
linux·运维·docker
Volunteer Technology3 小时前
Centos7安装python和jupyter
linux·python·jupyter
馨谙3 小时前
Linux面试题----rpm,dnf,Application Streams,Modules软件存储库
linux·运维·服务器
wdfk_prog3 小时前
[Linux]学习笔记系列 -- [drivers][base]core
linux·笔记·学习
tan 913 小时前
KaliLinux2025.4 root用户修改显示语言
linux·服务器·前端·安全