<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>嵌入式 Linux 基础 on Yun 的个人博客</title><link>https://yun7211.github.io/series/%E5%B5%8C%E5%85%A5%E5%BC%8F-linux-%E5%9F%BA%E7%A1%80/</link><description>Recent content in 嵌入式 Linux 基础 on Yun 的个人博客</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Mon, 18 May 2026 10:20:00 +0800</lastBuildDate><atom:link href="https://yun7211.github.io/series/%E5%B5%8C%E5%85%A5%E5%BC%8F-linux-%E5%9F%BA%E7%A1%80/index.xml" rel="self" type="application/rss+xml"/><item><title>根文件系统构建笔记</title><link>https://yun7211.github.io/embedded-linux/boot-system/rootfs-build-notes/</link><pubDate>Mon, 18 May 2026 10:20:00 +0800</pubDate><guid>https://yun7211.github.io/embedded-linux/boot-system/rootfs-build-notes/</guid><description>&lt;h2 id="根文件系统承担什么"&gt;根文件系统承担什么
&lt;/h2&gt;&lt;p&gt;Kernel 启动后需要挂载根文件系统，并运行第一个用户态进程。根文件系统里至少要有基础目录、初始化程序、命令工具、动态库、配置文件和设备节点。&lt;/p&gt;
&lt;p&gt;最小系统常见目录包括：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-txt" data-lang="txt"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/bin
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/sbin
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/etc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/lib
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/dev
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/proc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/sys
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/tmp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/var
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="init"&gt;init
&lt;/h2&gt;&lt;p&gt;Kernel 默认会尝试运行 &lt;code&gt;/sbin/init&lt;/code&gt;、&lt;code&gt;/etc/init&lt;/code&gt;、&lt;code&gt;/bin/init&lt;/code&gt; 或 &lt;code&gt;/bin/sh&lt;/code&gt;。如果这些路径都不存在，系统会 panic。&lt;/p&gt;
&lt;p&gt;调试时可以临时在 &lt;code&gt;bootargs&lt;/code&gt; 里指定：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-txt" data-lang="txt"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;init=/bin/sh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这样能绕过复杂启动脚本，先确认根文件系统能否进入用户态。&lt;/p&gt;
&lt;h2 id="动态库"&gt;动态库
&lt;/h2&gt;&lt;p&gt;如果应用或 BusyBox 是动态链接，需要把对应 C 运行库和动态加载器放进根文件系统。缺库时，常见现象是文件明明存在，却提示 &lt;code&gt;not found&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;可以用交叉工具链的 &lt;code&gt;readelf&lt;/code&gt; 或 &lt;code&gt;ldd&lt;/code&gt; 替代方案检查依赖。&lt;/p&gt;
&lt;h2 id="虚拟文件系统"&gt;虚拟文件系统
&lt;/h2&gt;&lt;p&gt;启动脚本通常需要挂载：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mount -t proc proc /proc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mount -t sysfs sysfs /sys
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mount -t devtmpfs devtmpfs /dev
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;缺少这些挂载会影响进程信息、设备节点和驱动状态查看。&lt;/p&gt;
&lt;h2 id="小结"&gt;小结
&lt;/h2&gt;&lt;p&gt;根文件系统问题要从两个角度看：Kernel 是否成功挂载它，用户态程序是否能在里面正常运行。先确认最小 shell 可用，再逐步恢复完整启动脚本。&lt;/p&gt;</description></item><item><title>设备树调试的几个检查点</title><link>https://yun7211.github.io/embedded-linux/drivers-dts/device-tree-debugging/</link><pubDate>Mon, 18 May 2026 10:10:00 +0800</pubDate><guid>https://yun7211.github.io/embedded-linux/drivers-dts/device-tree-debugging/</guid><description>&lt;h2 id="为什么设备树容易出问题"&gt;为什么设备树容易出问题
&lt;/h2&gt;&lt;p&gt;设备树描述硬件，但它本身不会证明硬件真的可用。一个节点看起来完整，也可能因为地址、时钟、中断、复位或引脚复用配置错误而导致驱动 probe 失败。&lt;/p&gt;
&lt;p&gt;调试设备树时，可以先围绕几个高频字段检查。&lt;/p&gt;
&lt;h2 id="compatible"&gt;compatible
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;compatible&lt;/code&gt; 决定设备节点能否匹配到驱动。驱动侧通常通过 &lt;code&gt;of_device_id&lt;/code&gt; 表匹配字符串。&lt;/p&gt;
&lt;p&gt;如果驱动没有 probe，先检查：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;字符串是否拼写一致&lt;/li&gt;
&lt;li&gt;驱动是否编进内核或模块已加载&lt;/li&gt;
&lt;li&gt;节点 &lt;code&gt;status&lt;/code&gt; 是否为 &lt;code&gt;okay&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="reg-和-ranges"&gt;reg 和 ranges
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;reg&lt;/code&gt; 描述寄存器地址和长度。地址单元数量受父节点的 &lt;code&gt;#address-cells&lt;/code&gt; 和 &lt;code&gt;#size-cells&lt;/code&gt; 影响。&lt;/p&gt;
&lt;p&gt;如果寄存器读写异常，要确认物理地址、长度和父总线地址映射是否正确。&lt;/p&gt;
&lt;h2 id="pinctrlclock-和-reset"&gt;pinctrl、clock 和 reset
&lt;/h2&gt;&lt;p&gt;很多外设 probe 成功但不能工作，问题往往在 pinctrl、clock 或 reset。&lt;/p&gt;
&lt;p&gt;常见检查项：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;引脚复用是否切到外设功能&lt;/li&gt;
&lt;li&gt;上拉、下拉、驱动能力是否符合硬件&lt;/li&gt;
&lt;li&gt;时钟是否被正确打开&lt;/li&gt;
&lt;li&gt;reset 是否释放&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="interrupt"&gt;interrupt
&lt;/h2&gt;&lt;p&gt;中断问题通常表现为驱动正常加载，但事件没有响应。需要确认中断号、触发方式和中断控制器引用是否正确。&lt;/p&gt;
&lt;h2 id="小结"&gt;小结
&lt;/h2&gt;&lt;p&gt;设备树调试要同时看 DTS、驱动匹配表、内核日志和硬件原理图。只看一个文件很容易误判。&lt;/p&gt;</description></item><item><title>嵌入式 Linux 启动流程速记</title><link>https://yun7211.github.io/embedded-linux/boot-system/linux-boot-flow/</link><pubDate>Mon, 18 May 2026 10:00:00 +0800</pubDate><guid>https://yun7211.github.io/embedded-linux/boot-system/linux-boot-flow/</guid><description>&lt;h2 id="启动主线"&gt;启动主线
&lt;/h2&gt;&lt;p&gt;嵌入式 Linux 的启动过程可以先抓住一条主线：硬件上电后，Boot ROM 找到第一阶段启动程序，随后加载 U-Boot，再由 U-Boot 加载 Linux Kernel、设备树和根文件系统。&lt;/p&gt;
&lt;p&gt;完整路径通常是：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-txt" data-lang="txt"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Power On -&amp;gt; Boot ROM -&amp;gt; SPL/TPL -&amp;gt; U-Boot -&amp;gt; Kernel -&amp;gt; init -&amp;gt; user space
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;不同芯片的细节会变化，但定位问题时先把当前卡在哪一段确认清楚，排查效率会高很多。&lt;/p&gt;
&lt;h2 id="boot-rom"&gt;Boot ROM
&lt;/h2&gt;&lt;p&gt;Boot ROM 是芯片内部固化代码，负责根据启动引脚或熔丝配置选择启动介质，例如 eMMC、SD 卡、SPI NOR、NAND 或 USB 下载模式。&lt;/p&gt;
&lt;p&gt;这一阶段常见问题包括启动介质不可读、镜像偏移不对、签名校验失败、供电和时钟没有满足芯片要求。&lt;/p&gt;
&lt;h2 id="u-boot"&gt;U-Boot
&lt;/h2&gt;&lt;p&gt;U-Boot 负责初始化更多硬件，并准备 Kernel 运行环境。常见动作包括初始化 DRAM、加载镜像、传递启动参数、加载设备树和设置 &lt;code&gt;bootargs&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;调试时优先确认：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;串口是否有输出&lt;/li&gt;
&lt;li&gt;DRAM 大小是否识别正确&lt;/li&gt;
&lt;li&gt;Kernel、DTB、rootfs 地址是否正确&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bootcmd&lt;/code&gt; 和 &lt;code&gt;bootargs&lt;/code&gt; 是否符合当前启动介质&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="kernel"&gt;Kernel
&lt;/h2&gt;&lt;p&gt;Kernel 接管后会解压、初始化内核子系统、解析设备树、挂载根文件系统并启动第一个用户态进程。&lt;/p&gt;
&lt;p&gt;如果 Kernel 已经打印日志但最终 panic，重点看 panic 前的最后几行。根文件系统挂载失败时，常见原因是驱动缺失、设备节点不匹配、文件系统类型不支持或 &lt;code&gt;root=&lt;/code&gt; 参数错误。&lt;/p&gt;
&lt;h2 id="小结"&gt;小结
&lt;/h2&gt;&lt;p&gt;启动问题不要一开始就陷入全部日志。先判断卡在 Boot ROM、U-Boot、Kernel 还是用户态，再按阶段收集证据，问题会清楚很多。&lt;/p&gt;</description></item></channel></rss>