恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

Zephyr BSP: 16-Zephyr Devicetree to C 代码生成全过程

  • 首页
  • 资讯中心
  • /
  • Zephyr BSP: 16-Zephyr Devicetree to C 代码生成全过程

相关资讯

AI眼镜PCBA代工怎么选?天地通 vs 通用方案深度对比 2026/9/29 10:54:17
仿muduo高并发网络库——Poller和EpollPoller 2026/9/29 10:54:17
RL-10-赵-Actor-Critic01-在线算法02:A2C算法04【优势函数由TD error来近似:A=δₜ=qₜ(s,a)-vₜ(s)≈rₜ₊₁(s,a)+γvₜ₊₁(s)-vₜ(s)】 2026/9/29 10:54:17

最新资讯

VCP-DCV 8.x备考指南:用实验代替刷题,攻克vSphere集群与高可用
Android架构实战:MVVM、Clean Architecture与模块化落地
Android架构实战:MVVM、Clean架构与模块化改造全解析
ThinkPad R61 BIOS设置全解析:菜单、参数与避坑指南
思科交换机基本配置指南:CLI视图、VLAN划分与SSH远程管理
Omarchy Quattro:面向开发者的开箱即用Linux桌面发行版

今日推荐

开源模型端侧落地实战:量化、推理加速与Agent上下文管理
AI Evals实战指南:从零搭建LLM应用评估体系与CI/CD集成
Java采购管理系统实战:从数据库设计到事务一致性

本周热门

从像素到笔画:srt-whiteboard-animation骨架笔迹追踪实现(Zhang-Suen细化+8邻接追踪)
网站建设的英语怎么说?别只背单词,看完这套安全完整流程才敢上线
新手入门看这篇:建设网站加盟避坑指南与SEO实操

本月精选

自研推理加速器Redwood:两周内实现PyTorch模型高效部署的实战教程
V4L2摄像头采集实战:从camera_client.rar到出图全流程解析
从“谁发明了钢琴键”到知识问答智能体:RAG与记忆工程实践

Zephyr BSP: 16-Zephyr Devicetree to C 代码生成全过程

发布时间:2026/9/29 10:54:17
Zephyr BSP: 16-Zephyr Devicetree to C 代码生成全过程 摘要:本文深入剖析 Zephyr RTOS 中 Devicetree 从.dts文本到 C 代码中DT_*宏的完整生成链路。文章从整体流水线出发,依次讲解.dts/.dtsi/.overlay的合并与预处理、zephyr.dts与devicetree_generated.h的区别、EDT(Enhanced Devicetree)对象模型、Binding 的作用,以及DT_NODELABEL()、DT_PATH()、DT_ALIAS()、DT_CHOSEN()、DT_INST()、DT_REG_ADDR()、DT_IRQN()、DT_PROP()等核心宏的由来与用法。最终串联 Init Priority、Driver Dependency、Dependency Graph,揭示DEVICE_DT_DEFINE()如何将 Devicetree 节点转化为struct device,并给出 BSP 开发调试的实用检查清单。Zephyr Devicetree → C 代码生成全过程你前面已经把:13 Init Priority→14 Driver Dependency→15 Devicetree Dependency Graph串起来了。下一步非常关键:Devicetree 文件到底是怎么一步一步变成 C 代码里的 DT_NODELABEL()、DT_INST()、DT_PROP()、DEVICE_DT_DEFINE() 的?这篇建议重点解决一个问题:.dts 是文本,最终却能让 C 编译器看到各种 DT_* 宏。中间到底发生了什么?1. 先看完整流水线先建立一张总图:Devicetree Source │ │ ▼ board.dts / .dtsi │ │ │ C preprocessor │ ▼ merged devicetree │ │ ▼ dtc / edtlib │ ┌─────────────┴─────────────┐ │ │ ▼ ▼ zephyr.dts edt.pickle │ │ │ │ ▼ ▼ devicetree_generated.h Python EDT │ │ │ │ └─────────────┬─────────────┘ │ ▼ Zephyr build system │ ▼ C/C++ compiler │ ▼ Driversource│ ▼ DEVICE_DT_DEFINE(...)│ ▼ struct device │ ▼ final firmware这里最容易产生一个误解:Zephyr 不是简单地把 .dts 转换成一个 .h。实际上存在两条重要路线:DTS │ ┌────────┴────────┐ │ │ ▼ ▼ devicetree.h Python EDT │ │ │ └── binding / dependency / │ instance / property analysis │ ▼ C preprocessor │ ▼ DT_* macros │ ▼ Driver C code而EDT(Enhanced Devicetree)是理解现代 Zephyr Devicetree 的关键。2. 第一层:.dts 到底是什么?例如我们有:/{soc{uart0:serial@40004000{compatible="company,my-uart";reg=0x400040000x1000;interrupts=5;clock-frequency=48000000;status="okay";};};};这里描述的是:Node ├── name │ └── serial@40004000 │ ├── label │ └── uart0 │ ├── compatible │ └── company,my-uart │ ├── reg │ └── 0x40004000 0x1000 │ ├── interrupts │ └──5│ ├── clock-frequency │ └──48000000│ └── status └── okay注意:Devicetree 本身不是 C。它只是一个硬件描述语言。所以:DT_NODELABEL(uart0)并不是 .dts 里面天然存在的东西。它是 Zephyr 后续生成出来的C 宏接口。3. 第二层:.dtsi 和 .dts 先合并真实 Zephyr 项目中,通常不是一个 DTS 文件。例如:boards/ company/ my_board/ my_board.dts里面可能:#includelt;company/soc.dtsigt;uart0{status="okay";};而:soc.dtsi里面可能已经定义:uart0: serial@40004000{compatible="company,my-uart";reg=...;};所以最终并不是分别处理:soc.dtsi my_board.dts而是先形成:soc.dtsi │ │ board.dts │ ▼ C preprocessor │ ▼ merged DTSsource可以理解为:SoC 描述 + Board 描述 + Shield + overlay + chosen + aliases + 其他 .dtsi │ ▼ 最终 Devicetree4. Overlay 在什么时候进入?比如:boards/company/my_board/my_board.dts定义:uart0{status="okay";};你的应用又有:app.overlay里面:uart0{current-speed=lt;115200gt;;};最终得到:uart0 ├── compatible="company,my-uart"├── reg=...├── status="okay"└── current-speed=115200所以 overlay 并不是运行时配置。它是在build time修改 Devicetree。这一点非常重要:overlay │ ▼ buildtime│ ▼ Devicetree 被修改 │ ▼ C code 使用最终结果而不是:firmware running │ ▼ 读取 overlay完全不是这样。5. 第三层:C preprocessor 处理 DTS这是理解 Zephyr BSP 的一个关键点。Devicetree 的预处理阶段会处理:# include# define# if# ifdef之类的东西。因此:board.dts │ ├── include soc.dtsi ├── include bindings └── overlay │ ▼ preprocessed DTS之后才交给 Devicetree compiler / Zephyr Devicetree tooling。6. 第四层:生成 zephyr.dts构建过程中你通常可以在:build/zephyr/附近看到:zephyr.dts这个文件非常值得你直接打开看。它代表:最终合并之后的 Devicetree。例如:soc{uart0: serial@40004000{compatible="company,my-uart";reg=0x40004000 0x1000;interrupts=5;status="okay";};};此时:.dts .dtsi .overlay │ ▼ 最终 Devicetree │ ▼ build/zephyr/zephyr.dts7. zephyr.dts 和 devicetree_generated.h 不一样这是很多刚开始研究 Zephyr 的人最容易混淆的地方。你可以把它们理解成:zephyr.dts给人和 Devicetree 工具看的:Node ├── compatible ├── reg ├── interrupts ├── status └── propertiesdevicetree_generated.h给 C 编译器看的:# define DT_N_S_soc_S_serial_40004000 ...# define DT_N_S_soc_S_serial_40004000_REG_ADDR ...# define DT_N_S_soc_S_serial_40004000_IRQ ...也就是说:zephyr.dts │ │ Devicetree representation ▼ devicetree_generated.h │ │ C macro representation ▼ Csource8. 最关键的文件:devicetree_generated.h假设:uart0: serial@40004000{compatible="company,my-uart";reg=0x40004000 0x1000;interrupts=5;status="okay";};Zephyr 会生成大量宏。概念上类似:# define DT_N_S_soc_S_serial_40004000 ...然后:DT_NODELABEL(uart0)最终会通过宏展开找到对应 node identifier。9. 为什么 Devicetree Node 会变成奇怪的宏名字?这是 Zephyr Devicetree 最值得理解的机制之一。假设:soc{uart0: serial@40004000{...};};它有一个完整 path:/soc/serial@40004000Zephyr 需要把这个路径编码成 C identifier。于是概念上变成:/soc/serial@40004000 ↓ DT_N_S_soc_S_serial_40004000这里:/ → S @ → 处理成合法 identifier\- → 处理成合法 identifier具体编码规则比较复杂,但核心思想非常简单:把 Devicetree path 编码成合法的 C identifier。所以:Devicetreenode↓ canonicalnodeidentifier ↓ C preprocessor macro10. DT_NODELABEL(uart0) 是怎么来的?你写:# define UART_NODE DT_NODELABEL(uart0)看起来像:uart0直接变成 node。其实不是。可以把它理解成:DT_NODELABEL(uart0)│ ▼ DT_N_NODELABEL_uart0 │ ▼ DT_N_S_soc_S_serial_40004000也就是说:

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号