Feedback
Feedback

If you are having issues with the exercises, please create a ticket on DevZone: devzone.nordicsemi.com
Drag & Drop Files, Choose Files to Upload 您最多可以上传 2 个文件。
  • 简体中文
    Eng
    简体中文
  • 设备树 (Devicetree)

    在嵌入式系统固件开发中,硬件传统上是在头文件(.h 或 .hh)中描述的。nRF Connect SDK 借鉴了 Zephyr RTOS,使用一种更结构化、模块化的方法来描述硬件,即通过一种称为设备树(devicetree)的结构。TODAY!

    设备树是一种描述硬件的分层数据结构。所描述的硬件可以是开发套件、SoC、SiP 或模块,定义了从开发套件上 LED 的 GPIO 配置到外设的内存映射位置等所有内容。设备树使用一种特定的格式,由连接在一起的节点 (nodes)组成,每个节点包含一组属性 (properties)。

    以下部分衍生自设备树文档。

    设备树基础

    顾名思义,设备树是一种树状结构。这种树的人类可读文本格式称为 DTS(即 devicetree source)。

    这是一个 DTS 文件示例:

    /dts-v1/;
    / {
            a-node {
                    subnode_label: a-sub-node {
                            foo = <3>;
                    };
            };
    };
    Devicetree

    上面的树有三个节点:

    1. 一个根节点: /
    2. 一个名为 a-node 的节点,它是根节点的子节点
    3. 一个名为 a-sub-node 的节点,它是其子节点 a-node

    节点可以被赋予标签 (labels),标签是唯一的简写,可用于在设备树的其他地方引用该标记节点。在上方,a-sub-node 具有标签 subnode_label。一个节点可以没有、有一个或多个节点标签。

    设备树节点还可以具有属性 (properties)。属性是名称/值对。属性值可以是字符串、字节、数字的数组,或任何类型的混合。

    节点 a-sub-node 有一个名为 foo 的属性,其值为单元格值 3。foo 的值的类型和大小由 DTS 中封闭的尖括号(< 和 >)暗示。如果传达真假信息,属性值可能为空。在这种情况下,属性的存在或缺失就足以说明问题。

    设备树节点具有标识其在树中位置的路径 (paths)。与 Unix 文件系统路径类似,设备树路径是以斜杠 (/) 分隔的字符串,根节点的路径是单个斜杠:/。否则,每个节点的路径由该节点的祖先名称与节点自身名称连接而成,并以斜杠分隔。例如,a-sub-node 的完整路径是 /a-node/a-sub-node。

    设备树绑定 (YAML 文件)

    设备树绑定 (Devicetree bindings) 定义了 compatible 属性。它声明了对设备树节点内容的要求,并提供有关有效节点内容的语义信息。Zephyr 的设备树绑定定义为 YAML 文件。每个设备树节点必须有一个 compatible 属性。设备树节点通过 compatible 属性与其在设备树绑定中的定义进行匹配。

    下面是一个设备树绑定文件 (.yaml) 的示例,它定义了名为 nordic,nrf-sample 的 compatible 属性,其中包含一个名为 num-sample 的整型必填属性。

    compatible: "nordic,nrf-sample"
    properties:
      num-sample:
        type: int
        required: true
    YAML

    下面是一个示例 DTS 文件 (.dts),其中节点 node0 被设置为 compatible nordic,nrf-sample。这意味着 node0 节点必须具有必填属性 num-sample,且该属性必须被分配一个整数值。否则,构建将失败。

    node0 {
         compatible = "nordic,nrf-sample";
         num-sample = <3>;
    };
    Devicetree

    设备树绑定随 SDK 一起提供在 <install_path>\zephyr\dts\bindings 中(参见 Nordic Semiconductor 设备的设备树绑定)。在某些情况下,您需要定义自己的 YAML 文件,例如在创建自定义驱动程序时。这在 nRF Connect SDK 中级课程中有所涵盖。

    别名 (Aliases)

    在设备树中添加别名是很常见的。/aliases 节点包含作为别名的属性,其中属性的名称是该别名的名称,属性的值是对设备树中某个节点的引用,见下文。

    / {
            aliases {
                    subnode_alias = &subnode_label;
            };
    };
    Devicetree

    上面的代码片段将通过其标签 subnode_label 引用的节点 a-sub-node 分配给别名 subnode_alias。这里的目的是让您的 C/C++ 应用程序代码(例如:main.c)使用该别名。在板级 dts 文件中定义固定别名(例如:板上第一个 LED 的 led0)可以使应用程序代码更具可移植性,因为它可以避免硬编码变化的设备节点名称,并使应用程序代码能够更灵活地适应所用板卡的变化。

    访问设备树

    要在源代码中获取有关特定设备树节点的信息,您需要为其提供一个节点标识符 (node identifier)。这只是一个引用该节点的 C 宏。有多种方法可以获取节点标识符。

    最常用的两种方法是通过宏 DT_NODELABEL() 获取节点标签,以及通过宏获取别名。 DT_ALIAS().

    例如,要获取 a-sub-node 的节点标识符:

    DT_NODELABEL(subnode-label)
    C

    要获取分配给特定设备树属性的值,我们可以使用宏 DT_PROP(). 。例如,要获取分配给 foo 属性的值:

    DT_PROP(DT_NODELABEL(subnode-label), foo)
    C

    设备树示例

    让我们通过一个实际例子来更好地理解这些概念。nRF52833 DK 有四个用户可配置的 LED(PCB 标记为 LED1 – LED4),连接到 GPIO 引脚 P0.13 – P0.16,如下面从 nRF52833 DK 原理图(可在开发套件页面的 Downloads – > Hardware Files 中找到)获取的截图所示。

    nRF52833 DK LED 位置
    nRF52833 DK LED 引脚映射

    注意

    nRF54 系列 DK(例如 nRF54L15 DK)上 LED 和按钮的 PCB 标记“Silkscreen on PCB”现在与其在设备树中的定义一致。

    例如,PCB 标签“LED0”对应设备树中的“led0”。这与我们之前的开发套件有所不同,之前的开发套件使用“LED1”PCB 标记来引用“led0”设备树节点。

    DK 设备树文件

    这些硬件详细信息都在 nRF52833 DK 的设备树文件中进行了描述。让我们检查一下这个文件,它位于 <install_path>\zephyr\boards\nordic\nrf52833dk\nrf52833dk_nrf52833.dts

    nRF52833 DK 设备树文件
    1. DK 的设备树文件包含了开发套件中所使用的特定 SoC 变体的设备树。对于 nRF52833 DK,它是位于目录 <install_path>\zephyr\dts\arm\nordic 中的文件 nrf52833_qiaa.dtsi。使用此文件是因为它对应于 nRF52833 DK 上使用的 SoC 的封装变体和功能变体。DTSI 中的 I 代表 Include(包含)。dtsi 文件通常包含 SoC 级别的定义。它还包含引脚映射,定义在 nrf52833dk_nrf52833-pinctrl.dtsi
    2. nRF52833 DK 上的 LED1(请阅读上方的注意信息)的节点名称为 led_0,节点标签为 led0。节点标签通常用于引用节点,例如 &led0。
    3. led_0 有两个属性:gpios 和 label。
    4. 您可以看到属性 gpios 正通过 & 符号引用节点 gpio0。gpio0 定义在 SoC 设备树中,正如我们将在下一段中看到的。套件上 LED1 连接到 nRF52833 SoC 的 GPIO 引脚被定义为 GPIO 0 上的 pin 13 (P0.13),且为低电平有效。

    重要

    节点通常具有节点标签 (node label),但它也可以具有名为 label 的属性 (property)。例如,节点 led_0 具有节点标签 led0 和值为“Green LED 0”的标签属性。在这种情况下,label 属性添加了一个描述 LED 的人类可读字符串。使用 label 属性(例如 “Green LED 0″)来获取节点标识符的方法已弃用,不应再使用。相反,建议使用节点标签 (led0) 来获取节点标识符。

    alias 节点也定义在 DK 设备树文件中,见下图。

    nRF52833 DK 设备树
    /aliases 节点

    我们可以从 DK 设备树中的 /aliases 节点看到,通过其节点标签引用为 &led0 的节点 led_0 被赋予了别名 led0。这听起来可能有些多余;然而,这样做是为了确保所有带有 LED 节点的板卡都为其 LED 提供一致的别名(例如第一个 LED 为 led0),以便应用程序代码(例如 main.c)可以在不同的板卡上编译,而无需您手动检查 DTS 文件并弄清楚不同板卡上 LED 使用的节点标签。

    如果我们查看其他一些外设节点,您会注意到各种 pinctrl 属性(定义在 <install_path>\zephyr\dts\bindings\pinctrl\pinctrl-device.yaml 中)。例如,描述 UART0 外设的节点 &uart0 具有属性 pinctrl-0、pinctrl-1 和 pinctrl-names。

    nRF52833 DK 设备树
    &uart0 节点

    这是基于 Zephyr 的引脚控制 (pin control),并通过引脚控制设备树文件中定义的 &pinctrl 节点将特定的引脚配置分配给设备树节点。

    引脚控制设备树文件

    设备树文件依赖于引脚控制设备树文件来获取各种节点(LED 和按钮除外)的引脚映射。如上图所示,&uart0 节点引用了在此文件中定义的节点 &uart0_default 和 &uart0_sleep。引脚控制设备树文件位于 <install_path>\zephyr\boards\nordic\nrf52833dk\nrf52833dk_nrf52833-pinctrl.dtsi。

    1. &pinctrl 节点(定义在 <install_path>\zephyr\dts\bindings\pinctrl\nordic,nrf-pinctrl.yaml 中)在其子节点中包含所有设备引脚配置。
    2. 节点 uart0_default 编码了 UART0 外设默认状态的引脚配置。引脚控制 API 允许您根据状态为外设分配不同的引脚;两个标准状态是 default 和 sleep。
    3. 引脚配置在每个子节点内分组组织,其中每个组在 psels 属性中指定引脚功能选择列表。group1 节点是这些组之一,指定了 UART_TX 和 UART_RTS 的引脚配置。
    4. 一个组还可以指定所有指定引脚共有的共享引脚属性。group2 节点正在指定 UART_RX 和 UART_CTS 的引脚配置,并为它们两者设置 bias-pull-up 属性。

    SoC 变体设备树文件

    现在,检查位于目录 <install_path>\zephyr\dts\arm\nordic 中的 SoC 变体设备树 nrf52833_qiaa.dtsi。

    nRF52833 QIAA SoC 变体设备树
    1. SoC 变体设备树包含基础 SoC 设备树 nrf52833.dtsi,该文件位于同一目录中。
    2. 它包含与 SoC 变体(版本)相关的信息,例如 RAM 和 flash 的基地址及大小。

    基础 SoC 设备树文件

    SoC 设备树包含所有外设和系统块的 SoC 级硬件描述。检查位于目录中的基础 SoC 设备树 nrf52833.dtsi <install_path>\zephyr\dts\arm\nordic.

    nRF52833 SoC 设备树
    1. gpio0 节点在此定义。
    2. 该节点通过 compatible 属性指定其代表的硬件。驱动程序使用它来选择其支持的节点。
    3. 它还定义了节点的地址空间。

    这应该能让您对如何使用设备树描述和呈现硬件有一个基本的了解。要获取有关设备树的更多信息,您可以从此处下载设备树规范。

    Switch language?

    Progress is tracked separately for each language. Switching will continue from your progress in that language or start fresh if you haven't begun.

    Your current progress is saved, and you can switch back anytime.

    Register an account
    Already have an account? Log in
    (All fields are required unless specified optional)

    • 8 or more characters
    • Upper and lower case letters
    • At least one number or special character

    Forgot your password?
    Enter the email associated with your account, and we will send you a link to reset your password.