第 2 课 - 输入(按键)控制输出(LED)-设备树

在第一课中学习了如何安装NCS开发环境,以及如何新建一个工程,还有如何构建和下载到开发板。并运行了官方的LED闪烁例程。

设备树

我们继续跟着官方开发者学院的教程来学习第二课的课程。官方课程包含了以下几个知识点:

设备树
设备驱动模型
GPIO的通用API

个人觉得设备树应该算一个难点,因为对于没有接触过linux驱动开发的人员来说是一个全新的知识点。

设备树是一种树状结构。文件格式是*.dts

下面是一个示例 DTS 文件:

/dts-v1/;

/ {
    aliases {
        serial0 = &uart0;    // 别名 serial0 指向标签 uart0
    };

    soc {
        uart0: serial@ff000000 {  // 节点名称 serial@ff000000,标签 uart0
            compatible = "ns16550a";
            reg = <0xff000000 0x1000>;
        };
    };
};

设备树中有几个概念一定要搞清楚:节点名称标签别名属性.

1. 节点名称(Node Name)

  • 定义:每个设备树节点的唯一标识,通常由两部分组成:类型和地址(或其他标识符),格式为 @

示例:uart@ff000000 表示一个位于地址 0xff000000 的 UART 设备。

  • 作用:唯一标识同一父节点下的子节点。

内核通过节点名称匹配驱动(结合 compatible 属性)。

  • 规则:同一父节点下的子节点名称必须唯一。

地址部分(@ 后内容)可省略,但需保证名称唯一(如 i2c 控制器可能无需地址)。

2. 标签(Label)

  • 定义:在节点定义前附加的符号,用于在设备树中方便地引用该节点,语法为

示例:uart0: serial@ff000000,标签 uart0 可被其他部分通过 &uart0 引用。

  • 作用:简化节点引用,避免冗长的路径(如 /soc/serial@ff000000)。
    提高设备树源文件(.dts)的可读性和维护性。

  • 规则:标签在整个设备树中必须唯一。

编译后(生成 .dtb 文件),标签会被替换为节点的全路径或 phandle,不会保留。

3. 别名(Aliases)

  • 定义:在 aliases 节点中定义的全局简短名称,语法为 = &

示例:aliases { serial0 = &uart0; },通过 serial0 别名引用标签 uart0 对应的节点。

  • 作用:提供稳定的设备标识符(如系统可能依赖 serial0 作为默认控制台)。
    运行时可通过别名快速查找设备(如内核使用 of_alias_get() 获取节点)。

  • 规则:别名在 aliases 节点中定义,每个别名全局唯一。
    别名通常与标签结合使用,指向具体节点。

对比与关系

特性 节点名称 标签 别名
唯一性 同一父节点下唯一 全局唯一 全局唯一
语法 <type>@<address> <label>:node{...} aliases { name = &label; }
编译后保留 否(替换为路径或 phandle) 是(保留在 .dtb 中)
主要用途 节点标识与驱动匹配 设备树内部的便捷引用 运行时通过名称访问设备

总结

  • 节点名称是硬件的唯一标识符。

  • 标签简化设备树内部的引用,提高可读性。

  • 别名提供全局的友好名称,用于运行时访问设备。

设备树的 绑定(Bindings)

设备树的 绑定(Bindings) 是描述设备树节点如何与硬件或驱动匹配的规范,通常以 YAML 文件 的形式定义。这些文件标准化了设备树节点的属性、约束和兼容性要求,帮助开发者正确描述硬件,并确保内核驱动能够正确匹配设备。以下是设备树绑定的核心概念和 YAML 文件的详细说明:

1. 绑定文件的作用

  • 定义节点规范: 规定某个设备树节点(如传感器、外设控制器)需要哪些属性、子节点,以及它们的格式。

  • 驱动匹配:通过 compatible 属性将设备树节点与内核驱动关联。

  • 验证设备树:使用工具(如 dt-validate 和 dt-schema)检查设备树是否符合绑定的约束。

2. YAML 绑定文件的结构

一个典型的绑定文件包含以下部分:

  1. 兼容性标识(compatible
    定义设备节点的兼容性字符串,用于匹配驱动。

示例:


compatible:
  - const: "vendor,device-id"  # 必须的兼容性字符串
  - enum:                      # 可选的其他兼容性字符串
      - "vendor,device-v2"
      - "vendor,device-legacy"
  1. 属性(properties
    规定节点必须或可选的属性及其约束(类型、范围、描述等)。
properties:
  reg:
    description: "寄存器地址和长度"
    type: array
    items:
      - description: "基地址"
        type: int
      - description: "长度"
        type: int
  clock-frequency:
    description: "时钟频率(Hz)"
    type: int
    default: 1000000  # 默认值(可选)
  1. 子节点(child nodes)
    定义子节点的要求和结构。

patternProperties:
  "^gpio-[a-z0-9]+$":  # 正则匹配子节点名称(如 gpio-led)
    type: object
    properties:
      label:
        type: string
      pin:
        type: int
  1. 必需字段(required
    标记必须存在的属性或子节点。

required:
  - reg
  - interrupts
  1. 示例(examples
    提供合法的设备树节点示例。

示例:


examples:
  - |
    mydevice@0 {
        compatible = "vendor,device-id";
        reg = <0x1000 0x100>;
        interrupts = <1 IRQ_TYPE_EDGE_RISING>;
    };
  1. 完整的 YAML 绑定示例

# 绑定文件:vendor,device-id.yaml
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Vendor Device Binding

description: >
  Documentation for Vendor's XYZ Device.

compatible:
  - const: "vendor,device-id"

properties:
  reg:
    description: "寄存器地址和长度"
    type: array
    items:
      - description: "基地址"
        type: int
      - description: "长度"
        type: int
    minItems: 1
    maxItems: 2

  clock-frequency:
    description: "设备时钟频率(Hz)"
    type: int
    default: 1000000

  interrupt-names:
    type: string
    enum: [ "tx", "rx", "error" ]

required:
  - reg
  - interrupts

examples:
  - |
    // 合法节点示例
    device@1000 {
        compatible = "vendor,device-id";
        reg = <0x1000 0x100>;
        interrupts = <1 IRQ_TYPE_EDGE_RISING>;
        clock-frequency = <2000000>;
    };
posted @   NEIKOO  阅读(15)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示