RK3568设备树实战:从零开始手把手教你修改DTS文件(附常见外设配置示例)

RK3568设备树实战:从零开始手把手教你修改DTS文件(附常见外设配置示例)

如果你刚拿到一块基于RK3568的开发板,准备在上面跑自己的Linux系统,那么设备树(Device Tree)就是你绕不开的第一道坎。几年前,我第一次接触嵌入式Linux时,面对那些密密麻麻的.dts文件也是一头雾水——明明硬件连接都检查过了,驱动代码也写好了,可系统就是识别不到我的传感器。后来才发现,问题出在一个不起眼的设备树节点上,少写了一个status = "okay"。这种经历让我深刻体会到,在嵌入式Linux开发中,硬件描述驱动代码同等重要,而设备树正是连接二者的桥梁。

对于RK3568这样的现代ARM芯片,Linux内核已经完全依赖设备树来获取硬件信息。这意味着,无论你是要添加一个I2C温湿度传感器、配置一个GPIO控制的LED,还是启用某个串口,都需要通过修改设备树文件来告诉内核:“嘿,这块板子上有这个设备,地址在这里,中断号是那个”。本篇文章将从一个实战者的角度,带你彻底掌握RK3568设备树的修改方法。我不会只讲枯燥的语法,而是结合具体的硬件场景——比如为I2C5接口添加MPU6050陀螺仪、配置GPIO1_A0引脚控制LED——一步步演示如何操作,并解释背后的原理和容易踩的坑。

1. 理解RK3568设备树的基本框架与文件结构

在动手修改之前,我们得先搞清楚RK3568的设备树文件是怎么组织的。打开你的Linux内核源码目录,进入arch/arm64/boot/dts/rockchip/,你会看到一大堆.dts.dtsi.dtb文件。别被数量吓到,它们其实有清晰的层次关系。

核心文件角色解析:

  • rk3568.dtsi:这是Rockchip官方提供的芯片级描述文件。它定义了RK3568这颗SoC内部的所有硬件资源,比如四个Cortex-A55 CPU核心、各个外设控制器(I2C、SPI、UART等)的寄存器地址、中断号、时钟配置等。你几乎不需要修改这个文件,它是所有RK3568板卡的共同基础。
  • rk3568-evb1-ddr4-v10.dtsi:这是板级描述文件的“模板”或“通用部分”。它描述了基于RK3568的某款评估板(EVB)的硬件配置,比如DDR类型、电源管理、一些默认开启的外设等。不同的具体板卡可以引用它并覆盖或添加自己的配置。
  • rk3568-atk-evb1-ddr4-v10-linux.dts:这才是你最终要修改的具体板卡设备树文件。它通过#include指令包含了上述的.dtsi文件,然后在此基础上,针对你这块特定板卡的硬件差异进行配置。比如你的板子I2C1上接的是AT24C02而不是FT5206,就需要在这里修改。

文件包含关系的直观理解:

你可以把这种结构想象成面向对象编程中的继承:

// 伪代码类比
class rk3568_soc { /* 芯片通用属性 */ };          // 对应 rk3568.dtsi
class evb_board : public rk3568_soc { /* 评估板通用属性 */ }; // 对应 rk3568-evb1-ddr4-v10.dtsi
class my_board : public evb_board { /* 我的板子特有属性 */ }; // 对应你实际修改的 .dts 文件

关键目录与编译产出:

在开发过程中,你主要关注两个位置:

  1. 源码位置arch/arm64/boot/dts/rockchip/ - 存放所有.dts.dtsi源文件。
  2. 编译输出:编译后会在相同目录或arch/arm64/boot/dts/下生成对应的.dtb(Device Tree Blob)二进制文件,这个文件才是最终被内核加载的。

一个快速定位你要修改的文件的方法: 查看开发板配套资料或内核编译配置,确定你的板子对应的.dts文件名。通常可以从uboot启动日志中看到类似这样的信息:

[    0.000000] OF: fdt: Machine model: Rockchip RK3568 ATK EVB1 DDR4 V10 Board

对应的设备树文件很可能就是rk3568-atk-evb1-ddr4-v10-linux.dts

提示:在修改前,务必先备份原始文件。建议使用Git进行版本管理,每次修改都做好注释和提交记录。

2. 设备树语法核心精要:从节点到属性

设备树语法并不复杂,它本质上是一种结构化的键值对描述语言。我们通过一个最简单的LED节点例子来理解其核心概念。

节点(Node)的基本结构:

每个硬件设备或组件在设备树中都是一个节点。节点有名字,可以包含子节点,形成树状结构。根节点是/,所有其他节点都是它的子孙。

// 这是一个完整的节点定义示例
led1: led@1 {                    // 节点标签:节点名@单元地址
    compatible = "gpio-leds";    // 属性:兼容性,用于匹配驱动
    label = "system_status";     // 属性:标签,方便用户识别
    gpios = <&gpio0 10 GPIO_ACTIVE_HIGH>; // 属性:GPIO资源引用
    linux,default-trigger = "heartbeat"; // 属性:Linux特定行为
    default-state = "on";        // 属性:默认状态
};

关键属性详解:

  1. compatible(兼容性):这是最重要的属性,没有之一。内核通过它来决定使用哪个驱动来管理这个设备。它的值是一个或多个字符串组成的列表,格式通常为"制造商,型号"。例如:

    • "rockchip,rk3568-i2c" 匹配RK3568的I2C控制器驱动
    • "ti,bq25601" 匹配TI的BQ25601充电芯片驱动
    • "gpio-keys" 匹配通用的GPIO按键驱动

    当有多个值时,内核会按顺序尝试匹配,直到找到合适的驱动。

  2. reg(寄存器区域):描述设备占用的地址空间。对于内存映射设备(如UART、SPI控制器),它指定寄存器块的起始地址和长度;对于I2C从设备,它指定设备地址。

    // 内存映射设备示例:UART2寄存器从0xfe660000开始,长度0x100
    uart2: serial@fe660000 {
        reg = <0x0 0xfe660000 0x0 0x100>;
    };
    
    // I2C从设备示例:设备地址为0x1e(7位地址)
    mpu6050@68 {
        reg = <0x68>;
    };
    
  3. status(状态):控制设备是否启用。常用值:

    • "okay""ok":启用设备
    • "disabled":禁用设备
    • 不写status属性时,默认等同于"okay"
  4. pinctrl-*(引脚控制):RK3568有强大的引脚复用功能,一个物理引脚可以作为GPIO、UART的TX、I2C的SCL等。pinctrl属性指定引脚的功能配置。

    &i2c1 {
        status = "okay";
        pinctrl-names = "default";
        pinctrl-0 = <&i2c1m0_xfer>;  // 使用i2c1m0_xfer这个引脚配置
    };
    
  5. clocksclock-names(时钟):指定设备使用的时钟源。RK3568的时钟树比较复杂,通常直接引用芯片头文件中定义的时钟。

    &uart2 {
        clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>;
        clock-names = "baudclk", "apb_pclk";
    };
    

地址单元与大小单元:#address-cells#size-cells

这两个属性决定了子节点r

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值