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_NODELABEL、DT_PROP、DEVICE_DT_GET |
| 覆盖文件 | 修改配置无需修改原设备树 |
掌握设备树可以帮助您:
- 硬件解耦:代码与硬件配置分离
- 平台适配:一套代码支持多硬件
- 配置灵活:通过配置文件修改硬件参数
- 代码复用:通用配置可以复用
建议在实际项目中:
- 从现有设备树模板开始
- 使用覆盖文件进行定制
- 遵循绑定文件规范
- 添加详细注释
参考资料: