Zephyr学习 第四章 - 1:从 DEVICE_DT_DEFINE 到 struct device
04-1从 DEVICE_DT_DEFINE 到 struct device验证方式Zephyr 源码、ELF/map、native_sim/native/64验证结论源码确认 编译确认 模拟确认1. 本节目标本节建立 Zephyr Device Model 的第一条完整链路Devicetree node - DT_INST_FOREACH_STATUS_OKAY - DEVICE_DT_INST_DEFINE - struct device device_state init entry - kernel 在 main 前调用 init - DEVICE_DT_GET 取得 device pointer - device_is_ready 检查初始化状态本节重点理解设备对象的组成和生命周期不深入初始化优先级、依赖排序和 API table 调度。第四章计划分为五节04-1 DEVICE_DT_DEFINE 与 struct device 04-2 初始化 level、priority 与启动顺序 04-3 初始化失败、依赖与 device_is_ready 04-4 driver API table 与子系统调用 04-5 多实例驱动、常见问题与第四章总结2. Device Model 解决什么问题不同驱动的硬件和业务不同但 Zephyr 希望用统一对象表达这个设备叫什么 它的只读硬件配置在哪里 它的可变运行状态在哪里 它提供什么 API 初始化是否已经执行并成功 它依赖哪些其他设备这就是struct device的职责。应用通常拿到conststructdevice*dev;然后检查设备是否 ready通过子系统 API 使用设备不直接了解驱动私有 data/config 的结构。3. 本地 Zephyr 的 struct device源码位置zephyr/include/zephyr/device.h:453核心字段可简化为structdevice{constchar*name;constvoid*config;constvoid*api;structdevice_state*state;void*data;/* 根据 Kconfig 还可能有 deps、PM、DT metadata 等字段 */};需要先记住五个核心指针字段含义常见存储性质name设备实例名称只读字符串config设备实例的固定配置static const通常 ROM/rodataapi驱动对外函数表static const通常 ROM/rodatastateZephyr 维护的公共初始化状态可变状态data驱动实例私有运行数据可变 RAM/BSS源码确认4. config 与 data 必须分开实验驱动定义structlearning_device_config{intinitial_value;};structlearning_device_data{intcurrent_value;bool init_was_called;};区别config 构建时由 Devicetree 决定 初始化后通常不改变 多数驱动声明为 static const data 运行过程中会改变 保存状态、buffer、callback、锁、计数等 不能声明为 const本节的具体值config.initial_value 42 data.current_value 0BSS 初值init 执行后data.current_value 42 data.init_was_called true5. Devicetree 实例overlay/ { learning_device0: learning-device-0 { compatible zephyr,learning-device; status okay; initial-value 42; }; };bindingcompatible:zephyr,learning-deviceinclude:base.yamlproperties:initial-value:type:intrequired:true生成结果#defineDT_N_INST_0_zephyr_learning_deviceDT_N_S_learning_device_0#defineDT_N_S_learning_device_0_P_initial_value42编译确认6. 每实例 config 和 data驱动使用#defineDT_DRV_COMPATzephyr_learning_device每实例展开宏#defineLEARNING_DEVICE_DEFINE(inst)\staticstructlearning_device_data\learning_device_data_##inst;\staticconststructlearning_device_config\learning_device_config_##inst{\.initial_value\DT_INST_PROP(inst,initial_value),\};\DEVICE_DT_INST_DEFINE(inst,learning_device_init,NULL,\learning_device_data_##inst,\learning_device_config_##inst,\POST_KERNEL,50,NULL);DT_INST_FOREACH_STATUS_OKAY(LEARNING_DEVICE_DEFINE)因为只有一个 status-okay 实例简化展开后会产生learning_device_data_0 learning_device_config_0 一个 struct device 一个 device_state 一个 init entry7. DEVICE_DT_INST_DEFINE 做了什么本地定义zephyr/include/zephyr/device.h:246#defineDEVICE_DT_INST_DEFINE(inst,...)\DEVICE_DT_DEFINE(DT_DRV_INST(inst),__VA_ARGS__)它只是先把inst转成 node identifier再调用DEVICE_DT_DEFINE(node_id,...)所以DEVICE_DT_DEFINE 接收明确 node identifier DEVICE_DT_INST_DEFINE 接收当前 DT_DRV_COMPAT 的 instance number驱动多实例模式通常使用后者。8. DEVICE_DT_DEFINE 做了什么本地定义zephyr/include/zephyr/device.h:229核心工作可以概括为1. 为 node 创建 device_state 2. 创建全局 struct device 3. 把 name/config/api/state/data 写入 device object 4. 注册 init function、level 和 priority 5. 把对象放进 Zephyr 特定 iterable/linker section它不是普通的局部变量声明也不是运行时malloc()。设备对象及初始化记录在链接阶段就已经存在于镜像中。9. 本节 DEVICE_DT_INST_DEFINE 参数DEVICE_DT_INST_DEFINE(inst,learning_device_init,NULL,learning_device_data_##inst,learning_device_config_##inst,POST_KERNEL,50,NULL);参数含义参数本实验值含义inst0当前 compatible instanceinit_fnlearning_device_init启动初始化函数pmNULL暂不使用设备电源管理datalearning_device_data_0私有可变数据configlearning_device_config_0私有只读配置levelPOST_KERNELkernel 可用后初始化prio50同 level 内的初始化优先级apiNULL本节暂不建立 API tablelevel 和 priority 将在 04-2 单独验证。10. init function 的输入staticintlearning_device_init(conststructdevice*dev){conststructlearning_device_config*configdev-config;structlearning_device_data*datadev-data;data-current_valueconfig-initial_value;data-init_was_calledtrue;return0;}初始化函数已经拿到了完整struct device因此能从中取得对应实例的 config 和 data。返回值0 初始化成功 非 0 初始化失败device 不应被认为 ready失败路径将在 04-3 用故障注入验证。11. init 为什么在 main 之前运行DEVICE_DT_DEFINE()不只是生成 device object还创建 init entry。Zephyr 启动代码按初始化 level 和 priority 遍历这些 entry在进入应用main()前调用相应 init function。本节选择POST_KERNEL, priority 50实际输出顺序[init] devicelearning-device-0 initial42 current_before0 *** Booting Zephyr OS build v4.1.0-rc1 *** [main] devicelearning-device-0 ready1 init_called1 initial42 current42结论learning_device_init() 先执行 main() 后执行并观察到 init 已修改 data模拟确认12. DEVICE_DT_GET 不是运行时查找main 中#defineLEARNING_DEVICE_NODEDT_NODELABEL(learning_device0)staticconststructdevice*constlearning_devDEVICE_DT_GET(LEARNING_DEVICE_NODE);本地定义#defineDEVICE_DT_GET(node_id)(DEVICE_DT_NAME_GET(node_id))这表示DEVICE_DT_GET 在编译/链接期引用 node 对应的全局 device object 不是按字符串遍历设备表 不会自动检查 init 是否成功如果 node 存在但没有驱动为它执行DEVICE_DT_DEFINE()通常会在链接时报错undefined reference to __device_dts_ord_N这是很重要的排查信号。13. node identifier 与 device pointer不要混淆DT_NODELABEL(learning_device0)这是预处理阶段使用的 node identifier。DEVICE_DT_GET(DT_NODELABEL(learning_device0))这是指向运行时struct device对象的 C pointer。转换关系node identifier - DEVICE_DT_GET - const struct device *node identifier 自己不是指针也不能传给运行时 device API。14. device_is_ready 的真实判断本地实现zephyr/kernel/device.c:132boolz_impl_device_is_ready(conststructdevice*dev){if(devNULL){returnfalse;}returndev-state-initialized(dev-state-init_res0U);}所以 ready 至少要求init function 已经被调用 init result 表示成功device_is_ready()不是Devicetree status 的别名真实总线通信测试传感器数据有效性测试永久保证设备以后不会出错。本节结果ready1因为 init 已执行并返回 0。模拟确认15. device name 从哪里来DEVICE_DT_DEFINE()使用DEVICE_DT_NAME(node_id)本地规则如果 node 有 label property - 使用 label property 字符串 否则 - 使用 node full name实验节点没有labelproperty因此dev-name learning-device-0不要把这里的dev-name再与 node labellearning_device0混淆。16. ELF 与 map 证据检查nm-n/mnt/c/study/1-zephyr/work/ch04_device_object/zephyr/zephyr.elf\|rglearning_device|__device_dts_ord|__init_实际关键 symbollearning_device_config_0 learning_device_data_0 learning_device_init __device_dts_ord_12 __init___device_dts_ord_12生成头文件说明#defineDT_N_S_learning_device_0_ORD12因此 ordinal 12 对应/learning-device-0。map 中还能看到.rodata.learning_device_config_0 .bss.learning_device_data_0 __device_dts_ord_12这与设计相符config - rodata data - BSS/RAM device init entry - 静态链接对象编译确认17. 本节最小构建cd~/project/exportZEPHYR_SDK_INSTALL_DIR/home/yff/zephyr-sdk/zephyr-sdk-0.17.1sourcezephyr/zephyr-env.sh west build\-bnative_sim/native/64\/mnt/c/study/1-zephyr/labs/ch04_device_model\--build-dir /mnt/c/study/1-zephyr/work/ch04_device_object\-palways /mnt/c/study/1-zephyr/work/ch04_device_object/zephyr/zephyr.exe实验不需要 GPIO、SPI、interrupt 或真实传感器验证的是 Zephyr Device Model 本身。19. 常见错误19.1 config 没有 const固定硬件配置通常应放在只读区。误放入可变 data 会增加 RAM 使用并模糊职责。19.2 在 config 中保存运行状态config 可能位于只读存储不能用于计数、callback 状态或实时数据。19.3 DEVICE_DT_GET 后不检查 ready取得 pointer 不表示 init 成功。conststructdevice*devDEVICE_DT_GET(node_id);if(!device_is_ready(dev)){/* handle error */}19.4 把 status okay 当 readystatus okay 只让实例参与构建ready 是 init 后的运行时状态。19.5 看到 __device_dts_ord_N undefined 就怀疑编译器通常应检查对应 driver Kconfig 是否为 ydriver.c是否进入编译node compatible/status 是否正确driver 是否执行DEVICE_DT_DEFINE/INST_DEFINE。19.6 在应用中直接访问 dev-data本实验为了教学展示内部结构。正常应用应通过驱动/子系统 API 使用设备避免依赖私有 data/config 类型。20. 可迁移到其他驱动的结论struct device是配置、数据、API 和公共状态的统一连接点config 通常static constdata 通常位于可变 RAMDEVICE_DT_INST_DEFINE()为 Devicetree instance 创建静态 device object 和 init entryDEVICE_DT_GET()取得全局对象地址不执行字符串查找也不检查 readydevice_is_ready()检查 init 已执行且返回成功status okay、device object 存在和 runtime ready 是不同阶段。下一节04-2-初始化level、priority与启动顺序。

相关新闻

大模型应用开发工程师:学习路线与职业发展指南

大模型应用开发工程师:学习路线与职业发展指南

1. 大模型应用开发工程师的职业前景 大模型应用开发工程师是当前AI领域最炙手可热的岗位之一。随着大模型技术的快速发展,各行各业都在积极探索如何将大模型能力整合到实际业务场景中。从智能客服到内容创作,从数据分析到决策支持,大模型正在…

2026/7/28 23:39:41阅读更多 →
MySQL数据库开发实战:从SQL语法到索引优化与性能调优

MySQL数据库开发实战:从SQL语法到索引优化与性能调优

在实际数据库开发中,很多开发者都经历过从只会写简单增删改查,到需要面对复杂查询、性能瓶颈和线上问题的阶段。MySQL作为最流行的开源关系型数据库,其核心在于如何高效、正确地使用SQL,并理解其背后的执行逻辑。本文旨在为希望系…

2026/7/28 23:39:41阅读更多 →
无人驾驶安全验证:方法论与实践挑战

无人驾驶安全验证:方法论与实践挑战

1. 无人驾驶安全验证的行业现状与挑战 2023年全球自动驾驶技术投资规模突破850亿美元,但美国IIHS数据显示,L2级自动驾驶系统每百万英里仍会发生9.1起可避免的碰撞事故。这个矛盾揭示了行业核心痛点:如何建立可信赖的安全验证体系。我在参与某…

2026/7/28 23:39:41阅读更多 →
ArkPets桌面宠物技术指南:明日方舟角色动态桌面集成方案

ArkPets桌面宠物技术指南:明日方舟角色动态桌面集成方案

ArkPets桌面宠物技术指南:明日方舟角色动态桌面集成方案 【免费下载链接】Ark-Pets Arknights Desktop Pets | 明日方舟桌宠 (ArkPets) 项目地址: https://gitcode.com/gh_mirrors/ar/Ark-Pets ArkPets是一款基于Java开发的明日方舟角色桌面宠物应用&#xf…

2026/7/29 0:57:59阅读更多 →
数据挖掘不靠运气,libsvm python一出手,隐藏信息全暴露

数据挖掘不靠运气,libsvm python一出手,隐藏信息全暴露

数据挖掘, 它是一种过程, 这个过程是从数量众多的数据里头, 借助算法去搜寻隐匿在其中的信息。数据挖掘常常跟计算机科学存在关联, 借助统计, 通过在线分析处理, 利用情报检索, 运用机器学习, 依靠按过去经验法则设计的专家系统, 再加上模式识别等众多方法, 去达成上述那个目标…

2026/7/29 0:57:59阅读更多 →
老Mac升级终极指南:3个简单步骤让旧设备运行最新macOS

老Mac升级终极指南:3个简单步骤让旧设备运行最新macOS

老Mac升级终极指南:3个简单步骤让旧设备运行最新macOS 【免费下载链接】OpenCore-Legacy-Patcher Experience macOS just like before 项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher 你是否还在为老Mac无法升级最新系统而烦恼&…

2026/7/29 0:57:59阅读更多 →
粉笔直播课适合税务系统考试突破吗

粉笔直播课适合税务系统考试突破吗

本文面向报考国家税务总局及各省税务局(国税/地税合并后统称税务系统)岗位、进入备考中后期且分数长期停滞的考生,围绕"突破瓶颈"这一核心诉求,评估粉笔直播课对税务系统考试的适配性。文中数据来源于公开财报、官网公示…

2026/7/29 0:57:59阅读更多 →
粉笔直播课适合气象局招聘突破吗

粉笔直播课适合气象局招聘突破吗

本文面向准备参加气象部门公开招聘(含国家气象局及地方气象局事业编、参公岗位)的考生,围绕"突破备考瓶颈"这一核心诉求,对粉笔直播课在该类考试中的适配性做客观拆解。文中数据来源于公开财报、官网公示价格、第三方投…

2026/7/29 0:57:59阅读更多 →
Silk v3解码器终极指南:3种方法轻松转换微信QQ语音文件为MP3

Silk v3解码器终极指南:3种方法轻松转换微信QQ语音文件为MP3

Silk v3解码器终极指南:3种方法轻松转换微信QQ语音文件为MP3 【免费下载链接】silk-v3-decoder [Skype Silk Codec SDK]Decode silk v3 audio files (like wechat amr, aud files, qq slk files) and convert to other format (like mp3). Batch conversion support…

2026/7/29 0:55:58阅读更多 →
覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

🔹 工具基础介绍 OpenClaw 是开源生态中一款实用性较强的本地智能工具,凭借本地离线运行、可视化图形操作和任务自动化三大核心特性,赢得了众多用户的青睐。与普通在线对话AI工具不同,它属于能够直接操控本机软硬件的智能数字员工…

2026/7/28 4:06:39阅读更多 →
伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

所谓液压伺服阀体的精密激光焊接,是用激光束对阀座壳体(通常为不锈钢或铝合金)进行密封焊接,使阀体在21-35MPa的高压液压油或压缩气体中长期运行而不发生介质泄漏。液压伺服阀是高端液压系统的"大脑"。从航空航天飞行控…

2026/7/28 2:08:06阅读更多 →
D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx 你是否还在…

2026/7/28 1:38:28阅读更多 →
28. Agent 执行到一半想暂停?用 interrupt 给它设个“关卡“!

28. Agent 执行到一半想暂停?用 interrupt 给它设个“关卡“!

28. Agent 执行到一半想暂停?用 interrupt 给它设个“关卡“! 在构建复杂的 Agent 系统时,我们经常会遇到这样的场景:Agent 正在执行一个多步骤的任务,比如“下单购买商品”,但执行到一半时,我们…

2026/7/29 0:01:46阅读更多 →
自律同行,突破无界!NANK南卡正式官宣曾舜晞成为品牌代言人

自律同行,突破无界!NANK南卡正式官宣曾舜晞成为品牌代言人

近日,国际专注开放式技术研发的声学品牌Nank南卡,正式官宣实力艺人曾舜晞担任品牌代言人。消息一经发出便轰动全网。为什么耳机品牌不选择流量明星、老牌歌手?而且是选择曾舜晞?让我们一起来探索一下!比起短期的流量&a…

2026/7/29 0:01:46阅读更多 →
【RT-DETR多模态创新改进】CVPR 2025 | 独家特征融合创新改进篇 | 引入RLAB残差线性注意力模块,有效融合并强调多尺度特征,多种改进点,适合红外与可见光融合目标检测任务,有效涨点

【RT-DETR多模态创新改进】CVPR 2025 | 独家特征融合创新改进篇 | 引入RLAB残差线性注意力模块,有效融合并强调多尺度特征,多种改进点,适合红外与可见光融合目标检测任务,有效涨点

一、本文介绍 🔥本文在RT-DETR多模态融合目标检测中引入RLAB残差线性注意力模块,可在不同模态特征交互阶段进行多次残差细化,使可见光、红外等特征在尺度、语义和空间位置上更好对齐;随后将细化特征与解码器输出拼接并生成Q、K、V,通过线性注意力自适应强化关键通道、目…

2026/7/29 0:01:46阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/28 20:22:24阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/28 3:17:03阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/28 2:35:58阅读更多 →