【Linux】正点原子开发板 Kernel-Panic 排查实录:从串口日志到根因定位
1. 串口日志里的 Kernel-Panic 现场还原正点原子开发板i.MX6ULL、STM32MP157、RK3568 这几类都算在 uboot 阶段用 tftp 把zImage和.dtb拉进内存、再bootz启动时最容易撞上的就是这一行[ 4.547787] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)它的字面意思是内核已经把驱动、调度、内存管理都初始化完了走到最后一步要挂载根文件系统结果发现root指定的设备根本不存在或者内核压根没识别到那块存储。unknown-block(0,0)里的两个 0 是关键——主设备号 0、次设备号 0说明内核连块设备节点都没建出来不是挂载失败而是没找到要挂的东西。这个报错和普通的驱动 oops 不一样。oops 通常还能留个半死不活的 shellpanic 是内核主动放弃直接停在那行end Kernel panic不动了。所以排查思路不是去读调用栈里某个函数而是倒推内核启动时到底认没认到 eMMC/SD 卡root参数指向的分区在不在我试过在正点原子 i.MX6ULL 上复现这个问题串口consolettymxc0,115200打出来的完整日志里panic 之前其实藏着线索。往上翻几十行会看到类似[ 4.537091] b310 4096 mmcblk1boot1 (driver?) [ 4.542426] b308 4096 mmcblk1boot0 (driver?)mmcblk1boot0、mmcblk1boot1是 eMMC 的 boot 分区mmcblk1p1、mmcblk1p2才是普通分区。如果日志里只出现了mmcblk1boot0/boot1却没有mmcblk1p1/p2那基本可以断定内核认到了 eMMC 控制器但没解析出分区表或者分区表本身是空的。这时候root/dev/mmcblk1p2自然找不到panic 就来了。还有一种情况是设备树dtb传错了。正点原子的板子分 eMMC 版和 NAND 版dtb 文件不一样比如imx6ull-14x14-evk-emmc.dtb和imx6ull-14x14-evk-nand.dtb。如果你 tftp 下载时手滑传了 NAND 版的 dtb内核就会按 NAND 的存储控制器去初始化eMMC 根本没被枚举日志里连mmcblk都不会出现。所以现场还原的第一步不是急着改bootargs而是把串口日志完整抓下来确认三件事内核有没有枚举到 mmc 设备、分区有没有被解析、root指向的设备节点是否存在。这三步定位清楚了后面改配置才有方向不然就是瞎试。2. TaoToken 前置把排查过程变成可对话的调试助手排查 Kernel-Panic 最烦的地方在于串口日志几百行panic 那行只是结果真正的原因藏在前面。人眼一行行翻容易漏尤其是dmesg级别的驱动初始化信息。这时候我会把日志丢给模型让它帮我做日志摘要 可疑点排序。TaoToken 在这里的角色是一个统一的模型接入层。它提供 OpenAI 兼容的接口你可以用同一套Base URL和API Key去调不同的模型不用为每个模型单独配环境。对嵌入式调试来说好处是你可以在本地写个小脚本把串口抓到的日志直接 POST 过去让模型返回最可能的三个原因 对应的验证命令。接入信息如下官网https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentAPI Base URLhttps://taotoken.net/api模型对话入口https://taotoken.net/api?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewriteAPI Keys 管理https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite如果你只是偶尔查一次日志用模型对话页面把日志粘进去就行。如果你在做一个长期的嵌入式项目反复要分析启动日志那用 Coding Plan 更划算可以把它当成一个常驻的调试助手https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite需要说清楚的是TaoToken 不替代你的串口工具minicom、picocom、SecureCRT也不替代 uboot。它只是帮你更快地从日志里找到可疑点。真正的验证还得靠你在板子上敲命令。3. 可复制配置uboot 环境变量与日志采集脚本这一节给的是能直接抄的配置。先说 uboot 侧。正点原子开发板进 uboot 后先确认当前环境变量printenv bootargs printenv bootcmd如果bootargs是空的或者root指向的设备不对就按下面的方式设置。以 eMMC 启动、根文件系统在mmcblk1p2为例setenv bootargs consolettymxc0,115200 root/dev/mmcblk1p2 rootwait rw saveenv注意几个细节consolettymxc0,115200里的ttymxc0是 i.MX6ULL 的调试串口不同板子可能不一样STM32MP157 是ttySTM0RK3568 是ttyFIQ0。写错了不会 panic但你看不到日志等于瞎调。rootwait很重要。eMMC 枚举是异步的如果内核在 mmc 还没就绪时就去挂载根文件系统就会报unknown-block(0,0)。加上rootwait让内核等设备出现再挂载能解决一部分偶发 panic。rw表示以读写方式挂载。调试阶段建议加上方便你改文件量产可以改成ro。然后是 tftp 下载和启动的完整命令。假设你的 tftp 服务器是192.168.1.100板子 IP 是192.168.1.50setenv ipaddr 192.168.1.50 setenv serverip 192.168.1.100 setenv gatewayip 192.168.1.1 tftp 0x80800000 zImage tftp 0x83000000 imx6ull-14x14-evk-emmc.dtb bootz 0x80800000 - 0x83000000这里bootz的三个参数分别是内核地址、initrd 地址没有就写-、dtb 地址。手打bootz的时候一定要小心从别处复制粘贴经常带进不可见字符导致 uboot 解析参数出错。excerpt 里提到的复制出来的某一个字符不对就是这个坑。日志采集方面如果你在 Linux 主机上用picocom可以这样把串口输出同时存文件picocom -b 115200 /dev/ttyUSB0 --imap lfcrlf --logfile boot.log--logfile会把所有串口输出写到boot.log。抓完 panic 日志后用 grep 快速定位grep -n -E mmcblk|Kernel panic|VFS|root boot.log这条命令会把 mmc 设备枚举、panic 行、VFS 报错、root 参数相关的行都列出来前后对照一眼就能看出问题。如果你想把日志自动发给模型分析可以写个简单的 Python 脚本import requests with open(boot.log, r, errorsignore) as f: log f.read() resp requests.post( https://taotoken.net/api/v1/chat/completions, headers{ Authorization: Bearer YOUR_API_KEY, Content-Type: application/json, }, json{ model: gpt-4o-mini, messages: [ {role: system, content: 你是嵌入式Linux调试专家请从启动日志中找出Kernel panic的根因按可能性排序并给出验证命令。}, {role: user, content: log}, ], }, ) print(resp.json()[choices][0][message][content])把YOUR_API_KEY换成你在 API Keys 页面拿到的 key 就行。模型 ID 按你实际用的填文档里有完整列表。4. 验证请求与成功结果怎么确认修复生效改完bootargs后不要直接saveenv就完事先手动启动一次验证setenv bootargs consolettymxc0,115200 root/dev/mmcblk1p2 rootwait rw bootz 0x80800000 - 0x83000000观察串口输出。成功的标志是这几行[ 4.5xxxxx] mmcblk1: mmc1:0001 Q2J54A 3.64 GiB [ 4.5xxxxx] mmcblk1: p1 p2 [ 4.6xxxxx] EXT4-fs (mmcblk1p2): mounted filesystem with ordered data mode [ 4.6xxxxx] VFS: Mounted root (ext4 filesystem) on device 179:2. [ 4.6xxxxx] devtmpfs: mounted [ 4.6xxxxx] Freeing unused kernel memory关键看两处mmcblk1: p1 p2说明分区表被正确解析了VFS: Mounted root说明根文件系统挂载成功。这两行出现panic 就不会再来。如果还是 panic但日志里已经出现了mmcblk1: p1 p2那问题可能出在文件系统类型上。比如你的根文件系统是 ext4但内核没编 ext4 驱动就会报VFS: Cannot open root device。这时候要么换文件系统要么重新编译内核把 ext4 编进去。验证通过后再saveenv固化saveenv然后reset重启一次确认冷启动也能正常进系统。这一步不能省因为有些环境变量在手动启动时生效但saveenv后 uboot 读取的顺序可能不一样。如果你是用模型辅助分析日志的验证成功后可以把修复前的日志 修复后的日志一起发给它让它对比确认根因判断是否准确。这个习惯能帮你积累排查经验下次遇到类似问题反应更快。5. 本篇常见错排查401、local proxy failed、reading choices、OAuth这一节对照真实报错把排查过程中容易撞的坑列清楚。401 Unauthorized调 TaoToken API 时最常见。原因通常是Authorization头没带或者 key 写错了。正确格式是Bearer YOUR_API_KEY注意Bearer和 key 之间有一个空格。如果你把 key 直接粘进代码里检查一下有没有多余的空格或换行。另外key 是在 API Keys 页面生成的别把官网登录密码当 key 用。local proxy failed这个报错通常出现在你本地配了 HTTP 代理但代理没启动或者地址不对。嵌入式调试环境里如果你在主机上设了http_proxy环境变量Python 脚本会默认走代理。解决办法是临时清掉unset http_proxy https_proxy或者在 requests 里显式禁用代理proxies {http: None, https: None} requests.post(url, proxiesproxies, ...)reading choices 报错这个一般是你解析模型返回时choices字段不存在。原因可能是请求体格式不对比如messages写成了message或者model字段填了一个不存在的模型 ID。先打印完整响应看看print(resp.status_code) print(resp.text)resp.text里通常会有具体的错误说明比如model not found或invalid request format。OAuth 相关报错如果你用的是 Claude Code 或者某些需要 OAuth 授权的客户端报错可能是 token 过期或回调地址不对。这类客户端接入时Base URL 要填https://taotoken.net/apiKey 填你生成的 API KeyModel ID 填文档里对应的模型名。三件套缺一不可少填一个就会报授权失败。如果你用的是 CC Switch 或 Cline MCP 这类工具配置里同样要写全三件套{ baseUrl: https://taotoken.net/api, apiKey: YOUR_API_KEY, model: claude-3-5-sonnet-20241022 }Codex 的auth.json也是类似结构base_url、api_key、model三个字段都要有。少一个就会出现OAuth或auth failed的报错。还有一个容易忽略的点uboot 里bootz的地址。0x80800000是内核加载地址0x83000000是 dtb 地址这两个地址不能重叠也不能超出内存范围。如果你 tftp 下载时地址写错内核可能加载到一半就崩日志里会出现Unable to handle kernel paging request这和 VFS panic 是两码事别混在一起排查。6. 语义一致 CTA把调试经验沉淀成可复用的流程Kernel-Panic 排查的核心不是记住某一条命令而是建立一套日志 → 可疑点 → 验证 → 固化的流程。串口日志抓全、grep 定位关键行、改bootargs验证、saveenv固化这四步走完大部分启动 panic 都能解决。如果你在调试过程中需要反复分析日志可以用 TaoToken 的模型对话入口快速问一次https://taotoken.net/api?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite如果你在做一个长期的嵌入式项目需要经常查日志、写驱动、调设备树Coding Plan 更适合当常驻助手https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite接入文档里有完整的模型列表和参数说明配置前先扫一眼能少踩很多坑https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite最后留一个实用技巧把这次成功的bootargs和bootcmd用printenv导出来存到本地文件里。下次板子环境变量被清空直接照着敲一遍就能恢复不用再从头排查。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →