Zephyr设备树完全指南

Zephyr设备树完全指南:作用、功能与使用方法

引言

在嵌入式系统开发中,硬件配置是一个复杂而关键的环节。不同的硬件平台有不同的外设配置、中断映射和内存布局。为了解决这个问题,Zephyr引入了设备树(Device Tree)机制,将硬件配置从代码中分离出来,实现了软件与硬件的解耦。

本文将深入介绍Zephyr中设备树的作用、功能和使用方法,帮助您全面理解和掌握这一重要技术。


一、设备树概述

1.1 什么是设备树

设备树(Device Tree,简称DT)是一种描述硬件设备信息的数据结构,起源于PowerPC架构,后来被Linux内核采用,现在广泛应用于嵌入式系统。
#mermaid-svg-QghTNS42dDFGPVZR{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-QghTNS42dDFGPVZR .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-QghTNS42dDFGPVZR .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-QghTNS42dDFGPVZR .error-icon{fill:#552222;}#mermaid-svg-QghTNS42dDFGPVZR .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-QghTNS42dDFGPVZR .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-QghTNS42dDFGPVZR .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-QghTNS42dDFGPVZR .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-QghTNS42dDFGPVZR .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-QghTNS42dDFGPVZR .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-QghTNS42dDFGPVZR .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-QghTNS42dDFGPVZR .marker{fill:#333333;stroke:#333333;}#mermaid-svg-QghTNS42dDFGPVZR .marker.cross{stroke:#333333;}#mermaid-svg-QghTNS42dDFGPVZR svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-QghTNS42dDFGPVZR p{margin:0;}#mermaid-svg-QghTNS42dDFGPVZR .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-QghTNS42dDFGPVZR .cluster-label text{fill:#333;}#mermaid-svg-QghTNS42dDFGPVZR .cluster-label span{color:#333;}#mermaid-svg-QghTNS42dDFGPVZR .cluster-label span p{background-color:transparent;}#mermaid-svg-QghTNS42dDFGPVZR .label text,#mermaid-svg-QghTNS42dDFGPVZR span{fill:#333;color:#333;}#mermaid-svg-QghTNS42dDFGPVZR .node rect,#mermaid-svg-QghTNS42dDFGPVZR .node circle,#mermaid-svg-QghTNS42dDFGPVZR .node ellipse,#mermaid-svg-QghTNS42dDFGPVZR .node polygon,#mermaid-svg-QghTNS42dDFGPVZR .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-QghTNS42dDFGPVZR .rough-node .label text,#mermaid-svg-QghTNS42dDFGPVZR .node .label text,#mermaid-svg-QghTNS42dDFGPVZR .image-shape .label,#mermaid-svg-QghTNS42dDFGPVZR .icon-shape .label{text-anchor:middle;}#mermaid-svg-QghTNS42dDFGPVZR .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-QghTNS42dDFGPVZR .rough-node .label,#mermaid-svg-QghTNS42dDFGPVZR .node .label,#mermaid-svg-QghTNS42dDFGPVZR .image-shape .label,#mermaid-svg-QghTNS42dDFGPVZR .icon-shape .label{text-align:center;}#mermaid-svg-QghTNS42dDFGPVZR .node.clickable{cursor:pointer;}#mermaid-svg-QghTNS42dDFGPVZR .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-QghTNS42dDFGPVZR .arrowheadPath{fill:#333333;}#mermaid-svg-QghTNS42dDFGPVZR .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-QghTNS42dDFGPVZR .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-QghTNS42dDFGPVZR .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-QghTNS42dDFGPVZR .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-QghTNS42dDFGPVZR .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-QghTNS42dDFGPVZR .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-QghTNS42dDFGPVZR .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-QghTNS42dDFGPVZR .cluster text{fill:#333;}#mermaid-svg-QghTNS42dDFGPVZR .cluster span{color:#333;}#mermaid-svg-QghTNS42dDFGPVZR div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-QghTNS42dDFGPVZR .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-QghTNS42dDFGPVZR rect.text{fill:none;stroke-width:0;}#mermaid-svg-QghTNS42dDFGPVZR .icon-shape,#mermaid-svg-QghTNS42dDFGPVZR .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-QghTNS42dDFGPVZR .icon-shape p,#mermaid-svg-QghTNS42dDFGPVZR .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-QghTNS42dDFGPVZR .icon-shape .label rect,#mermaid-svg-QghTNS42dDFGPVZR .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-QghTNS42dDFGPVZR .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-QghTNS42dDFGPVZR .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-QghTNS42dDFGPVZR :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 设备树
硬件描述语言
树形结构
平台无关
描述硬件组件
定义寄存器映射
配置中断
根节点
子节点
属性
同一代码适配多硬件
无需重新编译

1.2 设备树的作用

作用 说明
硬件抽象 将硬件信息从代码中分离
平台适配 一套代码支持多种硬件平台
配置灵活 修改配置无需重新编译代码
标准化 统一的硬件描述格式

1.3 设备树的优势

#mermaid-svg-XgkkWmobnhgreoM0{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-XgkkWmobnhgreoM0 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-XgkkWmobnhgreoM0 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-XgkkWmobnhgreoM0 .error-icon{fill:#552222;}#mermaid-svg-XgkkWmobnhgreoM0 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-XgkkWmobnhgreoM0 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-XgkkWmobnhgreoM0 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-XgkkWmobnhgreoM0 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-XgkkWmobnhgreoM0 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-XgkkWmobnhgreoM0 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-XgkkWmobnhgreoM0 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-XgkkWmobnhgreoM0 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-XgkkWmobnhgreoM0 .marker.cross{stroke:#333333;}#mermaid-svg-XgkkWmobnhgreoM0 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-XgkkWmobnhgreoM0 p{margin:0;}#mermaid-svg-XgkkWmobnhgreoM0 .pieCircle{stroke:#000000;stroke-width:2px;opacity:0.7;}#mermaid-svg-XgkkWmobnhgreoM0 .pieOuterCircle{stroke:#000000;stroke-width:1px;fill:none;}#mermaid-svg-XgkkWmobnhgreoM0 .pieTitleText{text-anchor:middle;font-size:25px;fill:#000000;font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-XgkkWmobnhgreoM0 .slice{font-family:"trebuchet ms",verdana,arial,sans-serif;fill:#000000;font-size:17px;}#mermaid-svg-XgkkWmobnhgreoM0 .legend text{fill:#000000;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:17px;}#mermaid-svg-XgkkWmobnhgreoM0 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 35% 25% 20% 20% 设备树优势 硬件解耦 配置灵活 代码复用 易于维护


二、设备树文件结构

2.1 文件类型

文件类型 后缀 说明
包含文件 .dtsi 可重用的设备树片段
设备树源文件 .dts 具体硬件的完整描述
覆盖文件 .overlay 修改或扩展现有配置

2.2 文件层次结构

#mermaid-svg-moaDuoYnMVwAwq3P{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-moaDuoYnMVwAwq3P .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-moaDuoYnMVwAwq3P .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-moaDuoYnMVwAwq3P .error-icon{fill:#552222;}#mermaid-svg-moaDuoYnMVwAwq3P .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-moaDuoYnMVwAwq3P .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-moaDuoYnMVwAwq3P .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-moaDuoYnMVwAwq3P .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-moaDuoYnMVwAwq3P .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-moaDuoYnMVwAwq3P .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-moaDuoYnMVwAwq3P .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-moaDuoYnMVwAwq3P .marker{fill:#333333;stroke:#333333;}#mermaid-svg-moaDuoYnMVwAwq3P .marker.cross{stroke:#333333;}#mermaid-svg-moaDuoYnMVwAwq3P svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-moaDuoYnMVwAwq3P p{margin:0;}#mermaid-svg-moaDuoYnMVwAwq3P .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-moaDuoYnMVwAwq3P .cluster-label text{fill:#333;}#mermaid-svg-moaDuoYnMVwAwq3P .cluster-label span{color:#333;}#mermaid-svg-moaDuoYnMVwAwq3P .cluster-label span p{background-color:transparent;}#mermaid-svg-moaDuoYnMVwAwq3P .label text,#mermaid-svg-moaDuoYnMVwAwq3P span{fill:#333;color:#333;}#mermaid-svg-moaDuoYnMVwAwq3P .node rect,#mermaid-svg-moaDuoYnMVwAwq3P .node circle,#mermaid-svg-moaDuoYnMVwAwq3P .node ellipse,#mermaid-svg-moaDuoYnMVwAwq3P .node polygon,#mermaid-svg-moaDuoYnMVwAwq3P .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-moaDuoYnMVwAwq3P .rough-node .label text,#mermaid-svg-moaDuoYnMVwAwq3P .node .label text,#mermaid-svg-moaDuoYnMVwAwq3P .image-shape .label,#mermaid-svg-moaDuoYnMVwAwq3P .icon-shape .label{text-anchor:middle;}#mermaid-svg-moaDuoYnMVwAwq3P .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-moaDuoYnMVwAwq3P .rough-node .label,#mermaid-svg-moaDuoYnMVwAwq3P .node .label,#mermaid-svg-moaDuoYnMVwAwq3P .image-shape .label,#mermaid-svg-moaDuoYnMVwAwq3P .icon-shape .label{text-align:center;}#mermaid-svg-moaDuoYnMVwAwq3P .node.clickable{cursor:pointer;}#mermaid-svg-moaDuoYnMVwAwq3P .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-moaDuoYnMVwAwq3P .arrowheadPath{fill:#333333;}#mermaid-svg-moaDuoYnMVwAwq3P .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-moaDuoYnMVwAwq3P .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-moaDuoYnMVwAwq3P .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-moaDuoYnMVwAwq3P .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-moaDuoYnMVwAwq3P .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-moaDuoYnMVwAwq3P .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-moaDuoYnMVwAwq3P .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-moaDuoYnMVwAwq3P .cluster text{fill:#333;}#mermaid-svg-moaDuoYnMVwAwq3P .cluster span{color:#333;}#mermaid-svg-moaDuoYnMVwAwq3P div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-moaDuoYnMVwAwq3P .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-moaDuoYnMVwAwq3P rect.text{fill:none;stroke-width:0;}#mermaid-svg-moaDuoYnMVwAwq3P .icon-shape,#mermaid-svg-moaDuoYnMVwAwq3P .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-moaDuoYnMVwAwq3P .icon-shape p,#mermaid-svg-moaDuoYnMVwAwq3P .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-moaDuoYnMVwAwq3P .icon-shape .label rect,#mermaid-svg-moaDuoYnMVwAwq3P .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-moaDuoYnMVwAwq3P .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-moaDuoYnMVwAwq3P .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-moaDuoYnMVwAwq3P :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 设备树文件层次
SoC级.dtsi
板级.dtsi
开发板.dts
应用.overlay
描述SoC外设
描述板级电路
具体开发板配置
应用特定配置

2.3 目录结构

复制代码
zephyr/
├── dts/
│   ├── bindings/           # 设备绑定文件
│   ├── common/             # 通用设备树
│   ├── arm/               # ARM架构
│   │   ├── nordic/        # Nordic SoC
│   │   │   ├── nrf52.dtsi
│   │   │   └── nrf52840.dtsi
│   │   └── st/            # STM32 SoC
│   │       └── stm32f4.dtsi
│   └── riscv/             # RISC-V架构
└── boards/
    └── arm/
        └── nrf52840dk_nrf52840/
            └── nrf52840dk_nrf52840.dts

三、设备树基本语法

3.1 节点定义

dts 复制代码
/* 设备树节点示例 */

/ {
    /* 根节点 */
    model = "Nordic nRF52840 DK";
    compatible = "nordic,nrf52840dk-nrf52840";
    
    /* 子节点 - 内存 */
    memory@20000000 {
        device_type = "memory";
        reg = <0x20000000 0x40000>;  /* 起始地址和大小 */
    };
    
    /* 子节点 - GPIO控制器 */
    gpio0: gpio@50000000 {
        compatible = "nordic,nrf-gpio";
        reg = <0x50000000 0x1000>;
        status = "okay";
        label = "GPIO_0";
    };
    
    /* 子节点 - UART */
    uart0: uart@40002000 {
        compatible = "nordic,nrf-uart";
        reg = <0x40002000 0x1000>;
        interrupts = <2 1>;
        status = "okay";
        current-speed = <115200>;
    };
};

3.2 属性类型

属性类型 语法 示例
字符串 name = "value"; model = "MyBoard";
32位整数 name = <value>; reg = <0x1000>;
整数数组 name = <v1 v2 v3>; reg = <0x20000000 0x40000>;
布尔值 name;name = "okay"; status = "okay";
字符串列表 name = "v1", "v2"; compatible = "a", "b";

3.3 特殊节点

dts 复制代码
/* 特殊节点示例 */

/ {
    /* chosen节点 - 运行时配置 */
    chosen {
        zephyr,console = &uart0;          /* 控制台串口 */
        zephyr,shell-uart = &uart0;       /* Shell串口 */
        zephyr,sram = &sram0;             /* SRAM区域 */
        zephyr,flash = &flash0;           /* Flash区域 */
        zephyr,code-partition = &code_partition;  /* 代码分区 */
    };
    
    /* aliases节点 - 别名定义 */
    aliases {
        led0 = &led0;
        sw0 = &sw0;
        uart0 = &uart0;
        i2c0 = &i2c0;
    };
    
    /* reserved-memory节点 - 保留内存 */
    reserved-memory {
        #address-cells = <1>;
        #size-cells = <1>;
        ranges;
        
        my_reserved: reserved@20001000 {
            reg = <0x20001000 0x1000>;
        };
    };
};

3.4 节点标签与引用

dts 复制代码
/* 节点标签与引用示例 */

/ {
    /* 定义带标签的节点 */
    gpio0: gpio@50000000 {
        compatible = "nordic,nrf-gpio";
        reg = <0x50000000 0x1000>;
        status = "okay";
    };
    
    /* 通过标签引用其他节点 */
    led0: led_0 {
        gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
        label = "LED0";
    };
    
    /* 通过路径引用 */
    &uart0 {
        current-speed = <9600>;  /* 修改uart0的属性 */
    };
};

四、设备树绑定

4.1 绑定文件概念

设备树绑定(Binding)定义了设备节点的属性规范,确保设备树的正确性和一致性。

复制代码
dts/bindings/
├── gpio/
│   ├── nordic,nrf-gpio.yaml
│   └── st,stm32-gpio.yaml
├── uart/
│   ├── nordic,nrf-uart.yaml
│   └── st,stm32-uart.yaml
└── i2c/
    └── nordic,nrf-twi.yaml

4.2 绑定文件示例

yaml 复制代码
# nordic,nrf-gpio.yaml

compatible: "nordic,nrf-gpio"

include: base.yaml

properties:
  reg:
    type: array
    description: |
      GPIO controller register space
      
  interrupts:
    type: array
    description: |
      Interrupt lines for each port
      
  label:
    type: string
    description: |
      Human readable string describing the device
      
  "#gpio-cells":
    const: 2
    description: |
      Number of cells in GPIO specifier
      
required:
  - reg
  - interrupts

4.3 绑定文件结构

字段 说明
compatible 兼容的设备列表
include 包含的基础绑定
properties 定义的属性列表
required 必填属性列表
description 属性描述

五、在代码中使用设备树

5.1 获取设备节点

c 复制代码
/* 获取设备节点示例 */

#include <zephyr/device.h>
#include <zephyr/devicetree.h>

/* 方式1:使用节点标签 */
#define UART_NODE DT_NODELABEL(uart0)

/* 方式2:使用别名 */
#define LED_NODE DT_ALIAS(led0)

/* 方式3:使用路径 */
#define GPIO_NODE DT_PATH(soc, gpio_50000000)

/* 获取设备指针 */
const struct device *uart_dev = DEVICE_DT_GET(UART_NODE);

/* 检查设备是否就绪 */
if (device_is_ready(uart_dev)) {
    printk("UART device is ready\n");
}

5.2 读取设备属性

c 复制代码
/* 读取设备属性示例 */

#include <zephyr/devicetree.h>

/* 读取整型属性 */
uint32_t baud_rate = DT_PROP(DT_NODELABEL(uart0), current_speed);
printk("Baud rate: %d\n", baud_rate);

/* 读取字符串属性 */
const char *label = DT_PROP(DT_NODELABEL(gpio0), label);
printk("GPIO label: %s\n", label);

/* 读取状态属性 */
if (DT_NODE_HAS_STATUS(DT_NODELABEL(uart0), okay)) {
    printk("UART is enabled\n");
}

5.3 GPIO配置

c 复制代码
/* GPIO设备树配置示例 */

#include <zephyr/drivers/gpio.h>

/* 使用别名获取LED节点 */
#define LED_NODE DT_ALIAS(led0)

/* 获取GPIO控制器和引脚 */
#define LED_GPIO DT_GPIO_CTLR(LED_NODE, gpios)
#define LED_PIN DT_GPIO_PIN(LED_NODE, gpios)
#define LED_FLAGS DT_GPIO_FLAGS(LED_NODE, gpios)

/* 获取设备 */
static const struct device *led_dev = DEVICE_DT_GET(LED_GPIO);

void led_init(void)
{
    /* 检查设备 */
    if (!device_is_ready(led_dev)) {
        printk("LED device not ready\n");
        return;
    }
    
    /* 配置引脚为输出 */
    gpio_pin_configure(led_dev, LED_PIN, GPIO_OUTPUT_INACTIVE | LED_FLAGS);
    
    /* 点亮LED */
    gpio_pin_set(led_dev, LED_PIN, 1);
}

5.4 中断配置

c 复制代码
/* 中断设备树配置示例 */

#include <zephyr/irq.h>

/* 获取中断号和优先级 */
#define MY_IRQ DT_IRQ_BY_IDX(DT_NODELABEL(my_device), 0, irq)
#define MY_IRQ_PRIORITY DT_IRQ_BY_IDX(DT_NODELABEL(my_device), 0, priority)

void my_interrupt_handler(const void *arg)
{
    printk("Interrupt triggered!\n");
}

void interrupt_init(void)
{
    /* 安装中断处理函数 */
    irq_connect(MY_IRQ, MY_IRQ_PRIORITY, my_interrupt_handler, NULL, 0);
    
    /* 使能中断 */
    irq_enable(MY_IRQ);
}

六、设备树覆盖文件

6.1 覆盖文件概念

设备树覆盖文件(Overlay)允许在不修改原始设备树的情况下,添加、修改或删除节点和属性。
#mermaid-svg-T7kjRsMrmd1VOTno{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-T7kjRsMrmd1VOTno .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-T7kjRsMrmd1VOTno .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-T7kjRsMrmd1VOTno .error-icon{fill:#552222;}#mermaid-svg-T7kjRsMrmd1VOTno .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-T7kjRsMrmd1VOTno .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-T7kjRsMrmd1VOTno .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-T7kjRsMrmd1VOTno .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-T7kjRsMrmd1VOTno .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-T7kjRsMrmd1VOTno .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-T7kjRsMrmd1VOTno .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-T7kjRsMrmd1VOTno .marker{fill:#333333;stroke:#333333;}#mermaid-svg-T7kjRsMrmd1VOTno .marker.cross{stroke:#333333;}#mermaid-svg-T7kjRsMrmd1VOTno svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-T7kjRsMrmd1VOTno p{margin:0;}#mermaid-svg-T7kjRsMrmd1VOTno .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-T7kjRsMrmd1VOTno .cluster-label text{fill:#333;}#mermaid-svg-T7kjRsMrmd1VOTno .cluster-label span{color:#333;}#mermaid-svg-T7kjRsMrmd1VOTno .cluster-label span p{background-color:transparent;}#mermaid-svg-T7kjRsMrmd1VOTno .label text,#mermaid-svg-T7kjRsMrmd1VOTno span{fill:#333;color:#333;}#mermaid-svg-T7kjRsMrmd1VOTno .node rect,#mermaid-svg-T7kjRsMrmd1VOTno .node circle,#mermaid-svg-T7kjRsMrmd1VOTno .node ellipse,#mermaid-svg-T7kjRsMrmd1VOTno .node polygon,#mermaid-svg-T7kjRsMrmd1VOTno .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-T7kjRsMrmd1VOTno .rough-node .label text,#mermaid-svg-T7kjRsMrmd1VOTno .node .label text,#mermaid-svg-T7kjRsMrmd1VOTno .image-shape .label,#mermaid-svg-T7kjRsMrmd1VOTno .icon-shape .label{text-anchor:middle;}#mermaid-svg-T7kjRsMrmd1VOTno .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-T7kjRsMrmd1VOTno .rough-node .label,#mermaid-svg-T7kjRsMrmd1VOTno .node .label,#mermaid-svg-T7kjRsMrmd1VOTno .image-shape .label,#mermaid-svg-T7kjRsMrmd1VOTno .icon-shape .label{text-align:center;}#mermaid-svg-T7kjRsMrmd1VOTno .node.clickable{cursor:pointer;}#mermaid-svg-T7kjRsMrmd1VOTno .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-T7kjRsMrmd1VOTno .arrowheadPath{fill:#333333;}#mermaid-svg-T7kjRsMrmd1VOTno .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-T7kjRsMrmd1VOTno .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-T7kjRsMrmd1VOTno .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-T7kjRsMrmd1VOTno .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-T7kjRsMrmd1VOTno .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-T7kjRsMrmd1VOTno .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-T7kjRsMrmd1VOTno .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-T7kjRsMrmd1VOTno .cluster text{fill:#333;}#mermaid-svg-T7kjRsMrmd1VOTno .cluster span{color:#333;}#mermaid-svg-T7kjRsMrmd1VOTno div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-T7kjRsMrmd1VOTno .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-T7kjRsMrmd1VOTno rect.text{fill:none;stroke-width:0;}#mermaid-svg-T7kjRsMrmd1VOTno .icon-shape,#mermaid-svg-T7kjRsMrmd1VOTno .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-T7kjRsMrmd1VOTno .icon-shape p,#mermaid-svg-T7kjRsMrmd1VOTno .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-T7kjRsMrmd1VOTno .icon-shape .label rect,#mermaid-svg-T7kjRsMrmd1VOTno .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-T7kjRsMrmd1VOTno .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-T7kjRsMrmd1VOTno .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-T7kjRsMrmd1VOTno :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 基础设备树
覆盖文件
合并后的设备树
SoC.dtsi
board.dts
修改节点
添加节点
禁用节点

6.2 覆盖文件示例

dts 复制代码
/* app.overlay - 应用覆盖文件 */

/ {
    /* 添加新节点 */
    my_sensor {
        compatible = "mycompany,my-sensor";
        reg = <0x40001000 0x100>;
        interrupts = <5 0>;
        status = "okay";
        label = "MY_SENSOR";
    };
    
    /* 修改现有节点 */
    &uart0 {
        current-speed = <9600>;  /* 修改波特率 */
        status = "okay";
    };
    
    /* 禁用节点 */
    &i2c0 {
        status = "disabled";  /* 禁用I2C0 */
    };
    
    /* 修改chosen节点 */
    &chosen {
        zephyr,console = &uart1;  /* 切换控制台到UART1 */
    };
};

6.3 使用覆盖文件

bash 复制代码
# 编译时指定覆盖文件
west build -b nrf52840dk_nrf52840 . -- -DDTC_OVERLAY_FILE=app.overlay

# 多个覆盖文件
west build -b nrf52840dk_nrf52840 . -- -DDTC_OVERLAY_FILE="app.overlay sensors.overlay"

七、设备树处理流程

7.1 编译流程

#mermaid-svg-iUPFYqyLYTktSOG4{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-iUPFYqyLYTktSOG4 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-iUPFYqyLYTktSOG4 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-iUPFYqyLYTktSOG4 .error-icon{fill:#552222;}#mermaid-svg-iUPFYqyLYTktSOG4 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-iUPFYqyLYTktSOG4 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-iUPFYqyLYTktSOG4 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-iUPFYqyLYTktSOG4 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-iUPFYqyLYTktSOG4 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-iUPFYqyLYTktSOG4 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-iUPFYqyLYTktSOG4 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-iUPFYqyLYTktSOG4 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-iUPFYqyLYTktSOG4 .marker.cross{stroke:#333333;}#mermaid-svg-iUPFYqyLYTktSOG4 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-iUPFYqyLYTktSOG4 p{margin:0;}#mermaid-svg-iUPFYqyLYTktSOG4 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-iUPFYqyLYTktSOG4 .cluster-label text{fill:#333;}#mermaid-svg-iUPFYqyLYTktSOG4 .cluster-label span{color:#333;}#mermaid-svg-iUPFYqyLYTktSOG4 .cluster-label span p{background-color:transparent;}#mermaid-svg-iUPFYqyLYTktSOG4 .label text,#mermaid-svg-iUPFYqyLYTktSOG4 span{fill:#333;color:#333;}#mermaid-svg-iUPFYqyLYTktSOG4 .node rect,#mermaid-svg-iUPFYqyLYTktSOG4 .node circle,#mermaid-svg-iUPFYqyLYTktSOG4 .node ellipse,#mermaid-svg-iUPFYqyLYTktSOG4 .node polygon,#mermaid-svg-iUPFYqyLYTktSOG4 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-iUPFYqyLYTktSOG4 .rough-node .label text,#mermaid-svg-iUPFYqyLYTktSOG4 .node .label text,#mermaid-svg-iUPFYqyLYTktSOG4 .image-shape .label,#mermaid-svg-iUPFYqyLYTktSOG4 .icon-shape .label{text-anchor:middle;}#mermaid-svg-iUPFYqyLYTktSOG4 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-iUPFYqyLYTktSOG4 .rough-node .label,#mermaid-svg-iUPFYqyLYTktSOG4 .node .label,#mermaid-svg-iUPFYqyLYTktSOG4 .image-shape .label,#mermaid-svg-iUPFYqyLYTktSOG4 .icon-shape .label{text-align:center;}#mermaid-svg-iUPFYqyLYTktSOG4 .node.clickable{cursor:pointer;}#mermaid-svg-iUPFYqyLYTktSOG4 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-iUPFYqyLYTktSOG4 .arrowheadPath{fill:#333333;}#mermaid-svg-iUPFYqyLYTktSOG4 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-iUPFYqyLYTktSOG4 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-iUPFYqyLYTktSOG4 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-iUPFYqyLYTktSOG4 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-iUPFYqyLYTktSOG4 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-iUPFYqyLYTktSOG4 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-iUPFYqyLYTktSOG4 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-iUPFYqyLYTktSOG4 .cluster text{fill:#333;}#mermaid-svg-iUPFYqyLYTktSOG4 .cluster span{color:#333;}#mermaid-svg-iUPFYqyLYTktSOG4 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-iUPFYqyLYTktSOG4 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-iUPFYqyLYTktSOG4 rect.text{fill:none;stroke-width:0;}#mermaid-svg-iUPFYqyLYTktSOG4 .icon-shape,#mermaid-svg-iUPFYqyLYTktSOG4 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-iUPFYqyLYTktSOG4 .icon-shape p,#mermaid-svg-iUPFYqyLYTktSOG4 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-iUPFYqyLYTktSOG4 .icon-shape .label rect,#mermaid-svg-iUPFYqyLYTktSOG4 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-iUPFYqyLYTktSOG4 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-iUPFYqyLYTktSOG4 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-iUPFYqyLYTktSOG4 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 设备树源文件
DTC编译
.dtb二进制文件
设备树解析
生成头文件
编译应用
.dtsi文件
.dts文件
.overlay文件
devicetree.h
devicetree_unfixed.h

7.2 生成的文件

文件 说明
devicetree.h 设备树常量定义
devicetree_unfixed.h 未固定的设备树定义
device_extern.h 设备外部声明

7.3 编译命令

bash 复制代码
# 查看设备树编译命令
west build -b <board> <app> -- -Dprintk-dtc

# 查看生成的设备树头文件
cat build/zephyr/include/generated/devicetree.h

# 验证设备树语法
dtc -I dts -O dtb -o test.dtb app.dts

八、常用设备树宏

8.1 节点访问宏

说明 示例
DT_NODELABEL(name) 通过标签获取节点 DT_NODELABEL(uart0)
DT_ALIAS(alias) 通过别名获取节点 DT_ALIAS(led0)
DT_PATH(...) 通过路径获取节点 DT_PATH(soc, uart)
DT_INST(n, compat) 通过实例号获取节点 DT_INST(0, nordic_nrf_uart)

8.2 属性访问宏

说明 示例
DT_PROP(node, prop) 读取属性值 DT_PROP(uart0, current_speed)
DT_NODE_HAS_PROP(node, prop) 检查属性是否存在 DT_NODE_HAS_PROP(uart0, status)
DT_NODE_HAS_STATUS(node, status) 检查状态 DT_NODE_HAS_STATUS(uart0, okay)

8.3 GPIO相关宏

说明 示例
DT_GPIO_CTLR(node, prop) 获取GPIO控制器 DT_GPIO_CTLR(led0, gpios)
DT_GPIO_PIN(node, prop) 获取GPIO引脚 DT_GPIO_PIN(led0, gpios)
DT_GPIO_FLAGS(node, prop) 获取GPIO标志 DT_GPIO_FLAGS(led0, gpios)

8.4 中断相关宏

说明 示例
DT_IRQ_BY_IDX(node, idx, prop) 获取中断属性 DT_IRQ_BY_IDX(dev, 0, irq)
DT_IRQ(node, prop) 获取中断 DT_IRQ(dev, interrupts)

九、设备树示例

9.1 完整设备树示例

dts 复制代码
/* nrf52840dk_nrf52840.dts */

#include <nrf52840.dtsi>

/ {
    model = "Nordic nRF52840 DK";
    compatible = "nordic,nrf52840dk-nrf52840";
    
    chosen {
        zephyr,console = &uart0;
        zephyr,shell-uart = &uart0;
        zephyr,sram = &sram0;
        zephyr,flash = &flash0;
    };
    
    aliases {
        led0 = &led0;
        led1 = &led1;
        led2 = &led2;
        led3 = &led3;
        sw0 = &sw0;
        sw1 = &sw1;
        sw2 = &sw2;
        sw3 = &sw3;
        uart0 = &uart0;
        i2c0 = &i2c0;
        spi0 = &spi0;
    };
    
    leds {
        compatible = "gpio-leds";
        led0: led_0 {
            gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
            label = "LED0";
        };
        led1: led_1 {
            gpios = <&gpio0 14 GPIO_ACTIVE_LOW>;
            label = "LED1";
        };
    };
    
    buttons {
        compatible = "gpio-keys";
        sw0: button_0 {
            gpios = <&gpio0 11 GPIO_ACTIVE_LOW>;
            label = "SW0";
        };
    };
};

/* 修改UART配置 */
&uart0 {
    current-speed = <115200>;
    status = "okay";
};

/* 配置I2C */
&i2c0 {
    clock-frequency = <I2C_BITRATE_FAST>;
    status = "okay";
};

9.2 覆盖文件示例

dts 复制代码
/* sensors.overlay - 传感器扩展 */

/ {
    /* 添加传感器节点 */
    hts221@5f {
        compatible = "st,hts221";
        reg = <0x5f>;
        label = "HTS221";
        status = "okay";
    };
    
    bme280@76 {
        compatible = "bosch,bme280";
        reg = <0x76>;
        label = "BME280";
        status = "okay";
    };
};

/* 修改I2C配置以支持传感器 */
&i2c0 {
    clock-frequency = <I2C_BITRATE_STANDARD>;
    status = "okay";
};

十、常见问题与解决方案

10.1 设备树语法错误

问题Error parsing device tree

解决

bash 复制代码
# 验证设备树语法
dtc -I dts -O dtb -o /dev/null app.dts

# 检查绑定文件
ls dts/bindings/gpio/

10.2 节点未找到

问题DT_NODELABEL: node 'uart0' not found

解决

dts 复制代码
/* 确保节点已定义 */
uart0: uart@40002000 {
    compatible = "nordic,nrf-uart";
    reg = <0x40002000 0x1000>;
    status = "okay";
};

10.3 属性未定义

问题DT_PROP: property 'current_speed' not found

解决

dts 复制代码
/* 在节点中添加属性 */
&uart0 {
    current-speed = <115200>;
};

10.4 设备未就绪

问题device_is_ready() returns false

解决

dts 复制代码
/* 确保设备状态为okay */
&uart0 {
    status = "okay";
};

10.5 中断配置错误

问题Interrupt not working

解决

dts 复制代码
/* 检查中断配置 */
my_device: device@1000 {
    compatible = "vendor,device";
    reg = <0x1000 0x100>;
    interrupts = <5 0>;  /* 中断号和优先级 */
    status = "okay";
};

十一、最佳实践

11.1 设备树组织建议

#mermaid-svg-qXTNBhQPSTIzvQU9{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-qXTNBhQPSTIzvQU9 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-qXTNBhQPSTIzvQU9 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-qXTNBhQPSTIzvQU9 .error-icon{fill:#552222;}#mermaid-svg-qXTNBhQPSTIzvQU9 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-qXTNBhQPSTIzvQU9 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-qXTNBhQPSTIzvQU9 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-qXTNBhQPSTIzvQU9 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-qXTNBhQPSTIzvQU9 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-qXTNBhQPSTIzvQU9 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-qXTNBhQPSTIzvQU9 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-qXTNBhQPSTIzvQU9 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-qXTNBhQPSTIzvQU9 .marker.cross{stroke:#333333;}#mermaid-svg-qXTNBhQPSTIzvQU9 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-qXTNBhQPSTIzvQU9 p{margin:0;}#mermaid-svg-qXTNBhQPSTIzvQU9 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-qXTNBhQPSTIzvQU9 .cluster-label text{fill:#333;}#mermaid-svg-qXTNBhQPSTIzvQU9 .cluster-label span{color:#333;}#mermaid-svg-qXTNBhQPSTIzvQU9 .cluster-label span p{background-color:transparent;}#mermaid-svg-qXTNBhQPSTIzvQU9 .label text,#mermaid-svg-qXTNBhQPSTIzvQU9 span{fill:#333;color:#333;}#mermaid-svg-qXTNBhQPSTIzvQU9 .node rect,#mermaid-svg-qXTNBhQPSTIzvQU9 .node circle,#mermaid-svg-qXTNBhQPSTIzvQU9 .node ellipse,#mermaid-svg-qXTNBhQPSTIzvQU9 .node polygon,#mermaid-svg-qXTNBhQPSTIzvQU9 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-qXTNBhQPSTIzvQU9 .rough-node .label text,#mermaid-svg-qXTNBhQPSTIzvQU9 .node .label text,#mermaid-svg-qXTNBhQPSTIzvQU9 .image-shape .label,#mermaid-svg-qXTNBhQPSTIzvQU9 .icon-shape .label{text-anchor:middle;}#mermaid-svg-qXTNBhQPSTIzvQU9 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-qXTNBhQPSTIzvQU9 .rough-node .label,#mermaid-svg-qXTNBhQPSTIzvQU9 .node .label,#mermaid-svg-qXTNBhQPSTIzvQU9 .image-shape .label,#mermaid-svg-qXTNBhQPSTIzvQU9 .icon-shape .label{text-align:center;}#mermaid-svg-qXTNBhQPSTIzvQU9 .node.clickable{cursor:pointer;}#mermaid-svg-qXTNBhQPSTIzvQU9 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-qXTNBhQPSTIzvQU9 .arrowheadPath{fill:#333333;}#mermaid-svg-qXTNBhQPSTIzvQU9 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-qXTNBhQPSTIzvQU9 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-qXTNBhQPSTIzvQU9 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qXTNBhQPSTIzvQU9 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-qXTNBhQPSTIzvQU9 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qXTNBhQPSTIzvQU9 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-qXTNBhQPSTIzvQU9 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-qXTNBhQPSTIzvQU9 .cluster text{fill:#333;}#mermaid-svg-qXTNBhQPSTIzvQU9 .cluster span{color:#333;}#mermaid-svg-qXTNBhQPSTIzvQU9 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-qXTNBhQPSTIzvQU9 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-qXTNBhQPSTIzvQU9 rect.text{fill:none;stroke-width:0;}#mermaid-svg-qXTNBhQPSTIzvQU9 .icon-shape,#mermaid-svg-qXTNBhQPSTIzvQU9 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qXTNBhQPSTIzvQU9 .icon-shape p,#mermaid-svg-qXTNBhQPSTIzvQU9 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-qXTNBhQPSTIzvQU9 .icon-shape .label rect,#mermaid-svg-qXTNBhQPSTIzvQU9 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qXTNBhQPSTIzvQU9 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-qXTNBhQPSTIzvQU9 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-qXTNBhQPSTIzvQU9 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 设备树组织
层次化设计
模块化拆分
注释规范
SoC层
板级层
应用层
按功能分组
复用.dtsi
节点说明
属性说明

11.2 实践建议

建议 说明
使用别名 通过aliases节点定义设备别名
复用dtsi 将通用配置放入.dtsi文件
使用覆盖 使用.overlay修改配置而非修改原文件
添加注释 为节点和属性添加说明
验证语法 使用dtc工具验证设备树语法

11.3 设备树风格指南

dts 复制代码
/* 良好的设备树风格 */

/ {
    /* 使用4空格缩进 */
    model = "My Board";
    compatible = "vendor,myboard";
    
    /* 节点按功能分组 */
    leds {
        compatible = "gpio-leds";
        
        /* 使用一致的命名 */
        led0: led_red {
            gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
            label = "LED_RED";
        };
    };
};

结束语

通过本文的详细介绍,相信您已经全面理解了Zephyr中设备树的概念和使用方法:

知识点 内容
设备树作用 硬件抽象、平台适配、配置灵活
文件类型 .dtsi(包含)、.dts(完整)、.overlay(覆盖)
基本语法 节点、属性、标签、引用
代码使用 DT_NODELABELDT_PROPDEVICE_DT_GET
覆盖文件 修改配置无需修改原设备树

掌握设备树可以帮助您:

  1. 硬件解耦:代码与硬件配置分离
  2. 平台适配:一套代码支持多硬件
  3. 配置灵活:通过配置文件修改硬件参数
  4. 代码复用:通用配置可以复用

建议在实际项目中:

  1. 从现有设备树模板开始
  2. 使用覆盖文件进行定制
  3. 遵循绑定文件规范
  4. 添加详细注释

参考资料

相关推荐
ScilogyHunter1 天前
Zephyr项目按需配置完全指南
zephyr
ScilogyHunter1 天前
Zephyr最简工程配置指南
zephyr
ScilogyHunter1 天前
Zephyr主仓库目录结构完全指南
zephyr
ScilogyHunter1 天前
Zephyr工程配置完全指南
zephyr
ScilogyHunter1 天前
Zephyr SDK按需配置完全指南
zephyr
ScilogyHunter1 天前
Zephyr编译生成的build目录完全解析
zephyr
ScilogyHunter1 天前
Zephyr开发中的Manifest文件完全解析
manifest·zephyr·west
ScilogyHunter2 天前
Zephyr概述
zephyr
ScilogyHunter2 天前
Zephyr SDK 目录结构详解
zephyr