设备树 aliases

在设备树(Device Tree)中,aliases(别名)是一种特殊的节点,它为设备树里的其他节点提供了更具可读性和方便使用的别名。这一特性让开发者在引用设备树节点时无需记住复杂的节点路径或名称,而是使用简洁且有意义的别名。

aliases节点通常位于设备树的根节点下,其内部包含一系列属性,每个属性名就是一个别名,属性值则是对应的节点路径。以下是一个简单的示例:

/ {
    model = "My Device";
    compatible = "mycompany,mymodel";

    aliases {
        serial0 = &uart0;
        i2c0 = &i2c_bus_0;
        gpio0 = &gpio_controller_0;
    };

    uart0: serial@12340000 {
        compatible = "arm,pl011";
        reg = <0x12340000 0x1000>;
    };

    i2c_bus_0: i2c@56780000 {
        compatible = "arm,pl013";
        reg = <0x56780000 0x1000>;
    };

    gpio_controller_0: gpio@9abc0000 {
        compatible = "arm,gpio-pl061";
        reg = <0x9abc0000 0x1000>;
    };
};

在上面这个例子中,aliases节点定义了三个别名:serial0、i2c0 和 gpio0,分别对应 uart0、i2c_bus_0 和 gpio_controller_0 节点。

如何使用 aliases

在设备树的其他地方,你可以使用这些别名来引用对应的节点。例如,你可以在某个节点的属性中使用别名来引用其他节点:

/ {
    // 省略其他部分

    some_device: some-device@def00000 {
        compatible = "mycompany,some-device";
        reg = <0xdef00000 0x1000>;
        // 使用别名引用 I2C 总线
        i2c-bus = <&i2c0>; 
    };
};

在上面的例子中,some_device 节点的 i2c-bus 属性使用别名 i2c0 引用了对应的 I2C 总线节点。

在内核代码里,你可以使用这些别名来引用对应的节点。例如,在内核代码中,你可以通过别名来查找设备:

#include <linux/of.h>

struct device_node *np;

np = of_find_node_by_alias(NULL, "serial0");
if (np) {
    // 处理找到的节点
    of_node_put(np);
}

在上面这个 C 代码示例中,of_find_node_by_alias 函数借助别名 “serial0” 查找对应的设备节点。

小结

  • 使用有意义的别名能够让设备树和内核代码更易读,开发者无需记住复杂的节点路径。
  • 当设备树的节点名称或路径发生变化时,只需修改 aliases 节点中的映射关系,而不用修改内核代码里的引用。

使用时需要注意的地方:

  • 别名在 aliases 节点中必须是唯一的,不能有重复的别名定义。
  • 别名的定义要与实际使用保持一致,避免出现引用错误。

aliases 和 label 的区别

在设备树里,label 和 aliases 都能让开发者更方便地引用节点,但它们在定义、用途和使用场景上还是存在一些差异的。
首先,定义方式上,label 是在节点或者属性前添加以冒号结尾的名称。例如:

cpu0: cpu@0 {
    device_type = "cpu";
    compatible = "arm,cortex - a9";
    reg = <0>;
};

这里的 cpu0 就是 cpu@0 节点的 label。
aliases 需要在设备树的根节点下创建一个名为 aliases 的节点,然后在该节点内通过属性来定义别名。例如:

aliases {
    serial0 = &uart0;
};

在上面的例子中,serial0 是 uart0 节点的别名,& 用于引用对应的节点标签。

从用途上看,label 主要用于在设备树文件内部引用节点。当你需要在设备树的其他地方对某个节点的属性进行修改或者添加新属性时,就可以借助 label 来引用该节点。例如:

&cpu0 {
    status = "okay";
};

这里的 &cpu0 引用了前面定义的 cpu0 标签对应的节点,并为其添加了 status 属性。
aliases 更侧重于为内核代码或者用户空间程序提供一种更易读、方便使用的方式来引用设备树节点。在内核代码中,开发者可以使用 of_find_node_by_alias 函数根据别名查找对应的设备节点,而无需记住复杂的节点路径。例如:

#include <linux/of.h>
struct device_node *np = of_find_node_by_alias(NULL, "serial0");
驱动开发核心理论,Linux内核开发入门实战视频教程:《Linux内核编程》,具有一线芯片原厂开发经验的驱动工程师录制,内含Linux设备树课程,教你如何修改设备树文件和基于设备树接口开发驱动。详情点击:王利涛老师个人淘宝店:Linux内核编程