深入理解设备树chosen节点:固件与内核的“配置桥梁”

电子说

1.4w人已加入

描述

 

 

在嵌入式 Linux 开发中,设备树(Device Tree)是连接硬件与内核的关键纽带。但有一个节点很特殊 —— 它不描述任何硬件模块,却直接决定内核能否正常启动,这就是chosen节点。

 

 

今天我们就从是什么、怎么工作、如何调试” 三个维度,结合流程图脑图,彻底搞懂chosen节点的核心逻辑,新手也能轻松入门。

 

 

一、chosen 节点:设备树中的 非硬件” 特殊存在

 

首先要明确一个关键点:chosen节点的本质是固件(如 U-Boot)与内核的配置传递通道,而非硬件描述节点。它的结构和功能都围绕传递启动参数” 展开。

 

 

1. 位置与结构:根节点下的 扁平节点

 

chosen节点始终是设备树根节点(/)的直接子节点,路径固定为/chosen,结构极简且无嵌套子节点,典型定义如下:

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
/ {    chosen {        bootargs = "earlycon=uart8250,mmio32,0x2ad40000 console=ttyFIQ0 root=PARTUUID=614e0000-0000 rw rootwait";        stdout-path = &uart0// 指向串口设备节点    };    // 其他硬件节点(描述CPU、外设等)    uart0: serial@2ad40000 { ... };    cpu0: cpu@0 { ... };};

无子节点:无需描述硬件层级,仅通过属性 ” 传递配置;

 

 

位置固定:必须在根节点下,确保固件和内核能快速定位。

 

 

2. 核心属性:传递启动配置的 钥匙

 

chosen节点的核心是属性,每个属性都对应内核启动的关键配置,最常用的 4 类属性如下表所示:

 

 

属性名

 

 

功能说明

 

 

典型值示例

 

 

优先级

 

 

bootargs

 

 

内核启动参数集合(最核心)

 

 

"console=ttyFIQ0 root=PARTUUID=xxx"

 

 

最高(决定启动核心逻辑)

 

 

stdout-path

 

 

标准输出设备(控制台)路径

 

 

&uart0(指向串口节点)

 

 

次高(补全控制台配置)

 

 

linux,initrd-start

 

 

initrd(内存盘)起始地址

 

 

0x88000000

 

 

按需使用(内存盘场景)

 

 

linux,initrd-end

 

 

initrd(内存盘)结束地址

 

 

0x89000000

 

 

按需使用(内存盘场景)

 

 

其中bootargs是重中之重,它包含控制台、根文件系统、权限等关键参数,例如:

 

 

earlycon=...:内核初始化早期启动串口输出(捕获早期日志);

 

 

root=PARTUUID=xxx:通过分区 UUID 定位根文件系统(避免设备名变动);

 

 

rw:根文件系统以可读写” 模式挂载。

 

 

3. 与硬件节点的 大核心区别

 

很多开发者会混淆chosen节点与硬件节点(如uart0cpu0),二者差异可通过下表快速区分:

 

 

对比维度

 

 

chosen节点

 

 

硬件节点(如uart0

 

 

核心作用

 

 

传递软件配置

 

 

描述硬件特性(地址、中断等)

 

 

可修改性

 

 

固件可动态修改(如 U-Boot bootargs

 

 

静态固定(由硬件手册决定)

 

 

依赖关系

 

 

不依赖硬件驱动

 

 

需内核驱动匹配才能生效

 

 

解析时机

 

 

内核启动最早期

 

 

驱动加载阶段

 

 

二、固件视角:为内核定制” 启动配置(附流程图)

 

固件(以最常用的 U-Boot 为例)是chosen节点的生产者,核心工作是根据硬件状态和用户需求,动态调整chosen配置,再传递给内核

 

 

固件处理 chosen 节点的完整流程

 

下图清晰展示了 U-Boot chosen节点的处理步骤,包含读取 修改 传递” 三个核心环节:

 

 

设备树

关键步骤解析

 

1.读取静态配置U-Boot 先加载设备树二进制文件(.dtb),读取.dts中预定义的bootargsstdout-path等默认值,相当于读取配置模板

 

 

2.动态修改属性:这是最核心的一步,U-Boot 会根据实际场景调整配置:

 

 

若用户在 U-Boot 命令行输入setenv bootargs "xxx",则覆盖chosen中的bootargs

 

 

若需加载 initrd(内存盘),则动态添加linux,initrd-startlinux,initrd-end属性;

 

 

stdout-path指向的串口不可用,则自动切换为可用设备(如从&uart0改为&uart1)。

 

 

1.传递设备树:修改完成后,U-Boot 通过架构特定方式(如 ARM r2寄存器)将.dtb地址传递给内核,确保内核能找到配置。

 

 

三、内核视角:解析配置,启动系统的第一指令(附流程图)

 

内核是chosen节点的消费者,会在启动最早期(甚至早于驱动加载)解析chosen节点—— 因为这直接关系到 能否正常启动

 

 

内核处理 chosen 节点的完整流程

 

下图展示了内核从找到配置” 到 应用配置” 的全流程,其中bootargs解析是核心环节:

 

 

设备树

关键步骤解析

 

1.早期定位节点:内核启动后第一步就是找到.dtb并定位/chosen节点,这一步必须”—— 比如earlycon参数需要在串口驱动加载前生效,才能捕获内核初始化早期的日志。

 

 

2.bootargs 解析与应用bootargs是内核启动的总开关,每个子参数都会交给对应模块处理:

 

 

console=xxx:串口子系统初始化对应终端(如/dev/ttyFIQ0),所有printk日志都输出到这里;

 

 

root=PARTUUID=xxxVFS(虚拟文件系统)根据 UUID 找到根分区,以rw模式挂载;

 

 

rootwait:块设备子系统等待存储设备(如 SD 卡)就绪,避免挂载失败。

 

 

1.暴露配置到用户态:内核启动后,会通过/proc/sys文件系统将chosen配置暴露给用户,方便调试(如cat /proc/device-tree/chosen/bootargs可查看实际生效的启动参数)。

 

 

四、整体协作:固件与内核的配置传递闭环


 

chosen节点的价值,本质是实现了固件与内核的信息闭环

 

 

信息是单向传递的:仅固件向内核传递配置,内核启动后不反向修改;

 

 

动态配置优先级更高:U-Boot 的动态修改(如用户自定义bootargs)会覆盖.dts的静态配置;

 

 

早期依赖强:内核必须先解析chosen节点,才能完成控制台、根文件系统等关键初始化。

 

 

五、实战调试:类常见问题与解决方案(附脑图)

 

嵌入式开发中,很多启动故障都与chosen节点相关。掌握以下调试方法,能快速定位问题:

 

 

chosen 节点核心知识脑图

 

先通过脑图梳理调试所需的核心知识点,方便快速查阅:

 

 

设备树

类常见问题解决方案

 

1.问题 1:控制台无输出

 

 

可能原因:bootargsconsole参数错误,或stdout-path指向不可用设备;

 

 

调试步骤:

 

 

i.执行cat /proc/device-tree/chosen/bootargs,确认console是否为正确终端(如ttyFIQ0);

 

 

ii.检查stdout-path是否指向存在的串口节点(如&uart0是否在设备树中定义);

 

 

iii.若需捕获早期日志,确认earlycon的串口地址(如0x2ad40000)与硬件手册一致。

 

 

1.问题 2:根文件系统挂载失败

 

 

可能原因:bootargsroot参数错误,或未加rootwait

 

 

调试步骤:

 

 

i.确认root参数类型(PARTUUID或设备名),用blkid命令验证PARTUUID是否匹配;

 

 

ii.若根文件系统在 SD 卡 / U 盘,检查是否添加rootwait参数(避免设备未就绪);

 

 

iii.查看内核日志(dmesg | grep root),定位具体挂载失败原因。

 

 

1.问题 3:丢失内核早期日志

 

 

可能原因:未配置earlycon参数,无法捕获驱动加载前的日志;

 

 

解决方案:在bootargs中添加earlycon=uart8250,mmio32,0x2ad40000(需替换为实际串口类型和地址)。

 

 

总结:chosen 节点的核心价值

 

chosen节点看似简单,却是嵌入式 Linux 启动流程中的 关键枢纽

 

 

对固件而言,它是定制启动配置” 的出口;

 

 

对内核而言,它是获取启动指令” 的入口;

 

 

对开发者而言,它是排查启动故障” 的重要抓手。

 

 

理解chosen节点的工作机制,不仅能快速解决启动问题,更能深入掌握固件与内核的协作逻辑—— 这也是嵌入式开发的核心能力之一。

 

 

你在开发中遇到过哪些与chosen节点相关的问题?欢迎在评论区分享,我们一起讨论解决方案!

 

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分