news 2026/9/29 6:38:06

Zephyr BSP: 19-手撕 struct device 的生成

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Zephyr BSP: 19-手撕 struct device 的生成

摘要:本文深入剖析 Zephyr 设备模型的核心机制,完整追踪一个 Devicetree 节点从DEVICE_DT_DEFINE()宏展开,到最终生成 ELF 中struct device对象的全过程。文章从struct device的四个核心成员(config、data、api、state)入手,逐步拆解DEVICE_DT_DEFINE()的宏调用链,阐明 Device Symbol、Config/Data/API 分离设计、Init Entry、Dependency Handle 等关键概念,并厘清dependency ordinal与init priority的本质区别。最后通过简化版手撕示例和 ELF 符号验证,帮助读者建立从源码到固件的完整认知,为将公司 SoC 接入 Zephyr 打下坚实基础。

从 DEVICE_DT_DEFINE() 手撕 struct device 的生成
TL;DR(太长不看版)

  • DEVICE_DT_DEFINE()是设备对象生成器,不是简单的struct device初始化,它向下调用DEVICE_DT_DEINIT_DEFINE()→Z_DEVICE_DEFINE(),最终生成 Device Object、Config、Data、API 和 Init Entry 五个部分。(见第三、四、十七节)
  • DEVICE_DT_GET()在编译期解析为&__device_dts_ord_xx,通过 Devicetree 宏直接取符号地址,不是运行时搜索设备。(见第七、八节)
  • Config / Data / API 三者分离:config 是静态硬件配置(ROM/RO),data 是运行时状态(RAM),api 是驱动操作接口(RO),struct device只是持有这三个指针的中心节点。(见第九~十三节)
  • Init Entry 与 Dependency Handles 是两条隐藏链:Init Entry 把初始化函数按 level + priority 放进 linker section,由 boot 阶段统一执行;Dependency Handles 记录设备间的依赖关系,用于设备排序与访问控制。(见十四~二十节)
  • dependency ordinal≠init priority:前者回答"设备在依赖图中的身份编号",后者回答"初始化阶段何时执行",两者最终在设备初始化系统中汇合。(见二十一节)

这一篇我们不再停留在:
“Zephyr 有一个 struct device。”
而是直接回答:
一个 DTS 节点,究竟是如何一步一步变成最终 ELF 里的 struct device 对象的?
核心目标是把这条链彻底打通:

DTS │ ▼ DT_NODELABEL(uart0)│ ▼ DEVICE_DT_DEFINE(...)│ ▼ DEVICE_DT_DEINIT_DEFINE(...)│ ▼ Z_DEVICE_DEFINE(...)│ ├── struct device ├── device_config ├── device_data ├── driver API ├── init entry └── dependency handles │ ▼ 最终 ELF │ ▼&\__device_dts_ord_xx │ ▼ struct device *

一、先看最终目标:我们到底想生成什么?
假设 Devicetree:

&usart1{status="okay";current-speed=<115200>;};

然后 driver 中写:

DEVICE_DT_DEFINE(DT_NODELABEL(usart1),uart_stm32_init,NULL,&uart_data,&uart_config,PRE_KERNEL_1,CONFIG_SERIAL_INIT_PRIORITY,&uart_driver_api);

最终我们希望得到一个类似这样的对象:

structdevice__device_dts_ord_XX={.name="usart1",.config=&uart_config,.api=&uart_driver_api,.data=&uart_data,.state=...,};

但这里有一个非常重要的认知:

你在源码中通常不会直接看到这样一个完整的 struct device 初始化器。

因为 Zephyr 用了大量宏,把它拆成多个编译期对象。

二、先回顾 struct device

Zephyr 的设备模型核心就是:

struct device

概念上可以简化成:

structdevice{constchar*name;constvoid*config;constvoid*api;void*data;structdevice_state*state;};

不同 Zephyr 版本的具体字段可能有所变化,所以这里重点不是字段数量,而是理解:

struct device │ ├── config │ ├── data │ ├── api │ └── state

其中:
config
硬件的静态配置:

structuart_stm32_config{uintptr_tbase;...};

通常放在只读区域。

data
运行时数据:

structuart_stm32_data{...};

通常位于 RAM。

api

driver 对外暴露的操作:

staticconststructuart_driver_apiuart_driver_api={.poll_in=...,.poll_out=...,...};

state
Zephyr 自己管理的 device state。

例如:

device initialized device initialization failed device power state

三、真正关键的宏

现在进入核心。

你看到:

DEVICE_DT_DEFINE(...)

不要把它理解成:

struct device xxx;

而应该把它理解成:

一个"设备对象生成器"。

四、第一层:DEVICE_DT_DEFINE()

概念上可以理解成:

#define DEVICE_DT_DEFINE(node_id, init_fn, pm, data, config, level, prio, api, ...)

它实际上会继续向下调用更底层的宏。

典型结构可以抽象成:

DEVICE_DT_DEFINE()│ ▼ DEVICE_DT_DEINIT_DEFINE()│ ▼ Z_DEVICE_DEFINE()│ ├──────────────┐ ▼ ▼ struct device dependency handles

注意:
真正值得研究的是 Z_DEVICE_DEFINE()。

五、为什么不能直接写 struct device?

假设我们自己写:

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/29 6:37:12

Hermes Agent 部署全指南:用 TaoToken 统一 Key 搭建你的第一个 AI 助手

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/29 6:35:22

Android Studio编译报错“No Module”全场景排查与修复指南

遇到 “Android Studio 无法编译运行 No Module” 这类报错&#xff0c;我第一反应不是去百度复制报错原文&#xff0c;而是先把 AS 右下角的 Gradle 同步状态栏和 Event Log 打开看一眼。因为这个错误在 Android Studio 里实在太“万金油”了——工程列表里没有模块、Gradle 面…

作者头像 李华
网站建设 2026/9/29 6:33:06

文生图模型盘点:设计师必备 AI 生图工具推荐(2026 版)——TaoToken 统一 Key 接入 Midjourney 与 Stable Diffusion 的配置骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/29 6:32:43

AI智能分析在Robin中的应用:如何让机器理解暗网数据

AI智能分析在Robin中的应用&#xff1a;如何让机器理解暗网数据 在当今数字化时代&#xff0c;暗网已经成为网络安全威胁的重要来源。Robin作为一款AI驱动的暗网OSINT工具&#xff0c;通过智能分析技术让机器能够深度理解暗网数据。本文将带您了解Robin如何运用AI技术解析暗网…

作者头像 李华