☰
Zephyr BSP: 05-Zephyr SoC Devicetree
2026/9/29 8:14:04 网站建设 项目流程

摘要:本文是 Zephyr SoC Porting 系列的第 5 篇,聚焦于如何通过 Devicetree 描述一个 SoC 的硬件资源。文章从 Devicetree 文件层次(.dts / .dtsi / .overlay / .yaml)讲起,厘清 SoC 公共硬件与 Board 特定硬件的职责划分;随后深入讲解 compatible、Binding、reg、interrupts、Clock、GPIO 等核心概念,并强调status = "disabled"的默认策略。最后通过west build生成的zephyr.dts与devicetree_generated.h,揭示 Devicetree 在编译期被转换为 C 宏的机制,帮助读者建立「SoC 描述硬件能力、Board 描述硬件连接」的核心认知,为后续 SoC Devicetree 实战打下基础。

Zephyr SoC Devicetree
如果你的最终目标是把公司的 SoC 正式加入 Zephyr 生态,那么这一篇非常关键。

前面你已经在学习:

01 Zephyr Hardware Model ↓ 02 Architecture → SoC → Board ↓ 03 Zephyr BSP ↓ 04 Zephyr SoC Porting ↓ 05 SoC Devicetree ← 现在

这一篇先不要急着写完整 Board,而是把一个问题彻底搞明白:

Zephyr 是如何通过 Devicetree 描述一个 SoC 的 CPU、RAM、Flash、Clock、UART、GPIO、Timer、Interrupt Controller 等硬件资源的?

Zephyr 官方也明确把 SoC 的硬件描述放在 dts//.dtsi 中,并要求使用该 SoC 的 Board 去 include 这个 .dtsi。

1. SoC Devicetree 到底是什么?
先不要把 .dtsi 理解成"配置文件"。
更准确地说:
SoC Devicetree 是 Zephyr 对 SoC 硬件拓扑和硬件资源的描述。
例如你的公司 SoC:

这些硬件资源最终都需要在 Devicetree 中有所描述。

所以你可以把:

soc.dtsi

理解成:
SoC 的硬件地图。

2. Zephyr 的 Devicetree 文件层次
一个比较典型的结构是:

官方文档把 Devicetree 输入分成四类:

.dts .dtsi .overlay .yaml

为了更直观地对比这四类文件,下面用一张表格总结它们的职责、内容与协作关系:

文件类型典型用途包含内容示例路径协作关系
.dtsBoard 级硬件描述Board 特有硬件(LED、Button、引脚复用、外设使能)boards/arm/nucleo_f303re/nucleo_f303re.dtsinclude 对应的 SoC.dtsi,并引用其中节点进行使能
.dtsiSoC / 公共硬件描述CPU、RAM、Flash、UART、GPIO、Clock 等 SoC 公共资源dts/arm/st/f3/stm32f303.dtsi被 Board.dtsinclude,提供 SoC 硬件能力
.overlay应用 / Board 的增量修改针对特定应用或 Board 的节点覆盖与追加app.overlay在编译期叠加到.dts之上,常用于修改status、引脚等
.yamlDevicetree binding节点允许的属性、类型与约束规则dts/bindings/serial/st,stm32-uart.yaml通过compatible与 DTS 节点匹配,指导驱动生成宏

简单来说:.dtsi描述 SoC 有什么,.dts描述 Board 怎么用,.overlay做增量修改,.yaml定义属性规则。四者最终在编译期合并为zephyr.dts,再生成驱动可用的 C 宏。

其中:

  • .dts:通常是 Board 的硬件描述
  • .dtsi:SoC 或公共硬件描述
  • .overlay:针对应用/Board 的修改
  • .yaml:Devicetree binding

3. .dts 和 .dtsi 的关系
这是做 SoC Porting 必须理解的地方。
假设你有:

Company SoC ↓ MY1234 ↓ 两个 Board ├── my1234_devkit └── my1234_eval

那么两个 Board 很可能共享:

my1234.dtsi

例如:

dts/ └── arm/ └── company/ └── my1234.dtsi

然后:

boards/ └── arm/ ├── my1234_devkit/ │ └── my1234_devkit.dts │ └── my1234_eval/ └── my1234_eval.dts

关系:

这就是为什么:
SoC 公共硬件放 .dtsi,Board 特有硬件放 .dts。

4. 一个 SoC .dtsi 应该描述什么?
对于公司 SoC,通常可以从这些东西开始:

CPU RAM Flash Interrupt Controller Clock UART GPIO Timer SPI I2C DMA PWM ADC...

例如:

#include<arm/armv7-m.dtsi>/{soc{compatible="company,my1234";uart0:uart@40000000{compatible="company,my-uart";reg=<0x400000000x1000>;interrupts=<50>;status="disabled";};gpio0:gpio@40010000{compatible="company,my-gpio";reg=<0x400100000x1000>;interrupts=<60>;status="disabled";};};};

这里暂时不用纠结具体 syntax。
先看结构:

soc │ ├── uart0 │ ├── gpio0 │ ├── spi0 │ ├── i2c0 │ └── timer0

这就是 SoC 的硬件资源树。

5. compatible 是最重要的东西之一
例如:

uart0: uart@40000000{compatible="company,my-uart";};

这里:

compatible="company,my-uart";

非常重要。
它实际上是在告诉 Zephyr:
这个节点是什么类型的硬件?

Zephyr 会根据 compatible 去寻找对应的 binding。
官方文档说明,Devicetree node 会通过 compatible 与 YAML binding 匹配。

例如:

DTS compatible="company,my-uart";│ ↓ dts/bindings/serial/company,my-uart.yaml │ ↓ UART Driver

所以:

DTS │ │ compatible ↓ Binding │ ↓ Driver

这是你以后做公司 SoC BSP 时必须牢牢记住的一条链。

6. Binding 是什么?

例如:

dts/bindings/serial/company,my-uart.yaml

可能:

description: Company UART compatible:"company,my-uart"include: - uart-controller.yaml

Binding 并不是驱动。

它更像:
告诉 Zephyr:这种硬件节点允许有哪些属性、这些属性是什么类型。

例如:

uart0: uart@40000000{compatible="company,my-uart";reg=<0x40000000 0x1000>;interrupts=<50>;current-speed=<115200>;status="okay";};

Binding 则告诉 Zephyr:

reg ↓ 这是地址/长度 interrupts ↓ 这是中断信息 current-speed ↓ 这是 UART 波特率 status ↓ 这是设备状态

官方文档也特别强调,binding 不仅用于验证 node 内容,还用于生成驱动和应用可使用的 Devicetree 宏。

7. SoC .dtsi 最核心的几个节点
对于你以后真正做公司 SoC BSP,我建议先重点理解下面这些。

7.1 CPU
例如:

cpus{# address-cells = <1>;# size-cells = <0>;cpu@0{device_type="cpu";compatible="arm,cortex-m4";reg=<0>;};};

它描述:

CPU │ └── Cortex-M4

如果你的公司 SoC 是:

Cortex-M33

那么这里的描述自然会不同。
如果是:

RISC-V

则整个 Architecture 层又不同。
这也正好对应你上一篇:

Architecture ↓ SoC ↓ Board

8. Memory

例如:

memory@20000000{compatible="mmio-sram";reg=<0x20000000 0x20000>;};

表示:

0x20000000 │ ├───────────────┐ │ │ ↓ ↓ RAM...128KB

Flash 也类似。
例如:

flash0: flash@8000000{compatible="soc-nv-flash";reg=<0x08000000 0x80000>;};

实际项目中具体 binding 和 flash controller 的描述会根据 SoC 架构而变化。

9. reg:描述硬件地址

这是 SoC Devicetree 中非常核心的概念。
例如:

uart0: uart@40000000{reg=&lt;0x40000000 0x1000&gt;;};

意思可以直观理解成:

UART0 Base: 0x40000000 Size: 0x1000

即:

于是驱动就知道:

UART registers ↓ 0x40000000

10. interrupts:描述中断连接
例如:

uart0: uart@40000000{interrupts=&lt;50&gt;;};

可以理解为:

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询