RK平台从编译到烧录:构建与烧录排障系统化 电子说
一次完整的开发闭环是「编译 → 烧录 → 升级 → 分区 → 启动」。这套链路每换一段都可能出问题,而每一段都有它自己的「证据」(报错信息、工具输出、日志、分区表)。本文基于触觉智能RK3576 Linux SDK,把这条链路从头到尾过一遍,问题、根因、命令串成一套,遇到卡点按段排查即可。

五个环节里,环境报错看 check-*.sh(01 编译)、烧录失败看工具与 Loader/MaskRom 模式、升级看 misc 引导与升级包、分区看 parameter.txt 与 rootfs:grow、启动卡死看日志阶段标志。下面按这个顺序展开。
一、编译环境都装好了,为什么一编译就报错?
别急着怀疑代码——这套 SDK 在动手编译前会先给环境做一次"体检",绝大多数报错信息里,其实就写着答案。
拿到 RK3576 Linux6.1 SDK 后第一件事不是改代码,而是先把编译环境对齐。这套 SDK(K1 新一代布局)内置了一套自动环境检查:每次 ./build.sh 或 make 启动时都会先跑 check_sdk,再按你选择的组件(内核 / Debian / Buildroot / Yocto…)分别跑对应的 check-*.sh。报错不是"玄学",而是这套检查脚本吐出来的结构化信息。报错信息里一般就带着解法:装哪个包、换哪个版本、改哪个目录权限。
1、这套 SDK 的"先体检,后编译"机制
入口在 device/rockchip/common/scripts/build.sh 的 main():
setup_environments:导出全套 RK_* 环境变量(SDK 目录、output 目录、芯片目录等);
check_sdk:先校验脚本路径没被搬错位置,然后执行 check-sdk.sh,并检测是否用 root 在编译;
各组件脚本(mk-kernel.sh / mk-rootfs.sh 等)内部再调 check-kernel.sh / check-debian.sh / check-buildroot.sh / check-yocto.sh 等。
这些 check-*.sh 全部位于 device/rockchip/common/scripts/ 下。所以排查"编译报错"的第一步,是先读懂报错是哪个检查脚本吐出来的,而不是直接去翻 Makefile。
官方依据:SDK 编译流程见 docs/cn/Rockchip_Developer_Guide_Linux_Software_CN.pdf 与根目录 README.md(Quick Start 五步:make help → make rockchip_defconfig → make menuconfig → make → 烧 output/firmware/update.img);环境检查机制以 device/rockchip/common/scripts/check-*.sh 源码为准。
2、一张表看懂环境报错(错误信息 → 原因 → 解法)
下表所有"报错关键字 / 解法"均直接摘自 SDK 源码(check-sdk.sh、check-kernel.sh、check-debian.sh、check-package.sh、build.sh),不是网上总结的通用经验。
| 报错关键字 | 含义 | 解法(摘自脚本给出的提示) |
|---|---|---|
| Current user is not the owner of SDK source! | 当前用户不是 SDK 源码属主(常见于 sudo 或换用户后) | sudo chown -h -R $(id -un):$(id -un) $RK_SDK_DIR/,或 su - $RK_OWNER 切回属主 |
| Please move SDK source code into an ext4 partition. | 源码所在分区不是 ext4/f2fs/btrfs(如 NTFS、FAT、挂载盘) | 把 SDK 移到 ext4 分区;SDK 只认 ext*|f2fs|btrfs |
| Your rsync/gcc/g++ is missing | 缺基础包(check-package.sh 统一输出) | sudo apt-get install rsync gcc g++ |
| Your python3 is too old for kernel: … | python3 版本太旧(内核 mkbootimg 跑不动) | 升级 python3(脚本会提示跑 install-python3.sh) |
| Your lz4 is too old for kernel: … | lz4 不带 favor-decSpeed(内核压缩 Image 需要) | 安装 lz4 v1.9.4(源码 git clone …/lz4 -b v1.9.4,sudo make install) |
| 缺 openssl/ssl.h、gmp.h、mpc.h、ncurses.h 等头文件 | 编译内核缺少 dev 开发包(check-header.sh 检查) | sudo apt-get install libssl-dev libgmp-dev libmpc-dev libncurses-dev flex |
| Please remount to allow creating devices… | 分区以 nodev 挂载(编 Debian 需要 mknod) | sudo mount -o remount,dev <挂载点> |
| Your mke2fs is too old: … | e2fsprogs 太旧,没有 -d 选项(打 ext4 根文件系统用) | 运行 install-e2fsprogs.sh 升级 |
| Your live-build doesn't support bookworm / Your debootstrap doesn't support bookworm | live-build / debootstrap 太旧,不支持 Debian 12(bookworm) | 按脚本提示用 salsa 源码分支重装 live-build / debootstrap |
| Your qemu-aarch64-static(qemu-user-static) is broken | chroot 模拟 arm64 环境的 qemu 坏了 | sudo apt-get install binfmt-support qemu-user-static --reinstall |
| Your qemu-aarch64 doesn't work with Debian(bookworm)! | qemu 版本与 bookworm 不兼容(需 qemu-8.0) | 用 SDK 自带 tools/x86_64/qemu-aarch64-static 替换后 reboot |
| No prebuilt GCC toolchain for …! |
SDK 预编译交叉工具链缺失(get_toolchain() 在 prebuilts/gcc/linux-x86/ |
检查 prebuilts/gcc/linux-x86/aarch64 目录是否完整,必要时重新 repo sync |
| Debian 源检查报错(编译 Debian 时) | check-network.sh 验证镜像源 RK_DEBIAN_MIRROR 不可达(本 SDK 默认 USTC 源) | 确保能访问镜像源,或改 RK_DEBIAN_MIRROR |
3、最容易踩的三个坑
坑 1:权限 / 目录不对,脚本直接拒跑
最典型的是用 sudo 或换用户编译。SDK 在 check-sdk.sh 里用 stat --format %U 取 SDK 属主,再和当前用户对比,不一致就报 Current user is not the owner of SDK source!。另外源码分区必须是 ext4/f2fs/btrfs——如果 SDK 解压在移动硬盘(NTFS)上,会直接报"请移到 ext4 分区"。
坑 2:版本"装了"但"太老"
这类报错最容易让人困惑:包明明装了啊。SDK 的检查不是"装了没",而是验证关键能力,例如:
lz4:跑 lz4 -h | grep favor-decSpeed,旧版没有这个特性就报错并建议装 v1.9.4;
python3:直接拿 kernel/scripts/mkbootimg 试跑,跑不动就报"too old";
mke2fs:必须支持 -d 选项;
qemu-user-static:要能配合 bookworm 的 ldconfig 跑起来,否则提示换 qemu-8.0。
坑 3:只编译内核 vs 全量编译,需要的包不一样
只编内核,检查的是 check-kernel.sh(flex、libssl-dev、libgmp-dev、libmpc-dev、libncurses-dev 等);一旦加编 Debian 根文件系统,就触发 check-debian.sh(debootstrap、qemu-user-static、binfmt-support、live-build)。很多人在内核编过后以为环境没问题,结果 buildroot/debian 阶段又报新错——因为那是另一组检查脚本。Buildroot 还要 expect(unbuffer),Yocto 要 zstd。
4、别等报错,先主动自查
# 1. 编译前先看帮助,确认选择路径make helpmake rockchip_defconfig # 或 ./build.sh rk3576:# 2. 关键包快速自查which python3 rsync gcc g++ flex debootstrap fakeroot zstd unbufferlz4 -h | grep favor-decSpeed # 看 lz4 能力dpkg -l | grep -E "libssl-dev|libgmp-dev|libmpc-dev|libncurses-dev|qemu-user-static|live-build"# 3. 确认 SDK 属主与分区stat -c '%U' . 2>/dev/null # 应与当前用户一致findmnt -fnu -o FSTYPE -T . # 应是 ext4/f2fs/btrfs
如果环境检查和命令都对,编译仍报错,那才进入"看构建日志"阶段——日志统一在 output/log/ 与 output/sessions/ 下,逐行看最终失败的命令。
5、避坑提醒
官方 推荐 Ubuntu 22.04;在 Ubuntu 24.04 上编译,官方 SDK Note 特别说明 v1.1.0 增强了 Debian 编译环境的检查与提示、v1.0.1 修复了 24.04 的编译异常——升级 SDK 或用 LTS 系统能少踩很多坑(依据:docs/cn/RK3576/RK3576_Linux6.1_SDK_Note.md)。
本 SDK 默认 Debian 12(bookworm)arm64,源码 debian/ubuntu-build-service/bookworm-xfce-arm64/;换其它版本/架构前先看 check-debian.sh 是否支持。
编译并行度由环境变量控制(本机示例 NINJAJOBS=48 / MAKEFLAGS=-j48),内存不够时先降并行度再谈其他。
"一编译就报错"在 RK3576 Linux6.1 SDK 里几乎都是环境检查拦截的结果,不是代码问题。处理顺序:① 看报错来自哪个 check-*.sh;② 按脚本提示装包/换版本/改权限;③ 用上文自查命令提前验证;④ 全量编译前把 kernel + rootfs 需要的包一次装齐。
二、烧录一直失败,是板子坏了还是工具不对?
绝大多数烧录失败,不是板子坏了,而是"设备没进对模式"或"工具没找到设备"。本文给你一张决策流程图。
烧录的本质:板子在 Loader 模式(或 MaskRom 模式)下,通过 USB 的 Rockusb 协议与 PC 端工具通信。工具下载镜像到对应分区。所以判断烧录失败,先回答三个问题:① 工具找到设备了吗?② 设备在哪个模式?③ 烧的是不是和分区匹配的镜像?
工具位置:Linux 用 tools/linux/Linux_Upgrade_Tool/Linux_Upgrade_Tool/upgrade_tool(本 SDK 为 v2.44);Windows 用图形工具 RKDevTool(SDK Note:v3.36)或命令行 tools/windows/upgrade_tool_v2.44.zip。官方文档:docs/cn/Linux/Recovery/Rockchip_Developer_Guide_Linux_Upgrade_CN.pdf。
1、烧录失败决策流程图
下面这张图是本文的核心,按顺序走就能定位绝大多数问题:

2、工具的命令集(实测输出)
直接在 SDK 里跑 upgrade_tool -h 就能看到完整命令。常用这几个:
| 命令 | 用途 |
|---|---|
| LD | ListDevice 列设备——烧录前第一件事 |
| CD / SD | ChooseDevice / SwitchDevice——多设备时选择 |
|
UL |
UpgradeLoader——烧 Loader(MaskRom 恢复的第一步) |
|
UF |
UpgradeFirmware——一键烧 update.img(推荐,免管分区) |
|
DI -p|-uboot|-trust|-b|-r|-m|-oem|-userdata|-rootfs |
DownloadImage 按分区烧单镜像 |
|
EF |
EraseFlash 擦除 Flash(换分区/换存储前先擦) |
| RD | ResetDevice 重启设备 |
| PL / RCI / SFI | 分区表 / 芯片信息 / 固件信息——确认板型与固件匹配 |
3、常见失败现象对照表
| 现象 / 报错 | 原因 | 处理 |
|---|---|---|
| 执行 DI/UF/UL 时报 No found any rockusb device,please plug device in!(或 LD 显示 List of rockusb connected(0)) | 工具没找到任何 Rockusb 设备 | 先确认板子是否已进入 Loader/MaskRom 模式(不是普通开机状态);换线换口;Type-C 必须用数据线 |
| 上电后是正常开机画面,不是"下载模式" | 板子没进 Loader 模式 | 按住 RECOVERY(下载)键 + RESET 再松开,或用系统内 reboot loader 进下载模式 |
| Linux 下 LD 没权限 / 看不到设备 | USB 设备权限(udev 规则)或驱动问题 | 确认用户有 USB 访问权限;Windows 下安装/重装 Rockchip 驱动(MaskRom 模式需专用驱动) |
| loader 被刷坏/清空后,识别成 MaskRom 设备 | Loader 丢失,芯片回落到 MaskRom | MaskRom 模式先 UL MiniLoaderAll.bin 恢复 Loader,再走正常流程 |
| 烧 di -p(parameter)失败 | parameter 与设备存储/既有分区不匹配 | 先 EF 擦除再烧;确认烧的是同一板型的 parameter(见 01.04) |
| 烧到一半卡住 / 报错退出 | 镜像与设备不符、USB 不稳定、存储异常 | 换稳定 USB 口;用 UF 烧整包 update.img;必要时重进 Loader 再试 |
注:MaskRom 与 Loader 模式的进入方式、Windows 驱动安装细节以官方 Upgrade_CN.pdf 与 RKDevTool 文档为准(模式机制属 RK 平台通用行为)。
4、SDK 自带的烧录脚本:rkflash.sh
SDK 已经把整包烧录流程写成了脚本 device/rockchip/common/scripts/rkflash.sh,它直接调用上面的 upgrade_tool。全量烧录(rkflash.sh 不带参数 = all)的执行顺序是:
upgrade_tool ul -noreset $LOADER # MiniLoaderAll.binupgrade_tool di -p $PARAMETER # parameter.txt(分区表)upgrade_tool di -uboot $UBOOT # uboot.imgupgrade_tool di -trust $TRUST # trust.imgupgrade_tool di -b $BOOT # boot.imgupgrade_tool di -r $RECOVERY # recovery.imgupgrade_tool di -m $MISC # misc.imgupgrade_tool di -oem $OEM # oem.imgupgrade_tool di -userdata $USERDATA # userdata.imgupgrade_tool di -rootfs $ROOTFS # rootfs.imgupgrade_tool rd # 重启
支持只烧某一个:./rkflash.sh boot、./rkflash.sh rootfs、./rkflash.sh loader、./rkflash.sh update(一键烧 update.img)、./rkflash.sh erase(擦除)。
镜像在哪:固件输出目录 output/firmware/(即 rockdev)。本 SDK 的 Loader 是 rk3576_spl_loader_v1.09.107.bin(软链到 u-boot/),boot.img 来自内核构建。
5、实操排查步骤
# 0. 工具与设备cd tools/linux/Linux_Upgrade_Tool/Linux_Upgrade_Tool./upgrade_tool LD # 看到 Rockusb 设备 = 连接成功# 1. 看不到设备 → 强制进 Loader# 按住 RECOVERY 键 + 复位/上电,然后再次 LD# 2. 进 MaskRom 后先恢复 Loader./upgrade_tool UL/rockdev/MiniLoaderAll.bin# 3. 正常烧录(二选一)./upgrade_tool UF /rockdev/update.img # 整包,最省事# 或单分区./upgrade_tool DI -p /rockdev/parameter.txt./upgrade_tool DI -b /rockdev/boot.img# 4. 烧完重启./upgrade_tool RD
烧录失败先别怀疑板子:① 用 upgrade_tool LD 看工具是否找到设备;② 找不到就强制进 Loader(RECOVERY 键),再不行考虑 MaskRom + UL 恢复 Loader;③ 走 rkflash.sh all 或 UF update.img 整包烧录最稳;④ 仍未解决才考虑硬件(换线/换口/换板)。
三、Recovery 进不去、OTA 刷不上,升级链路哪一环断了?
"进不去 recovery"和"OTA 刷不上"不是同一件事:前者是引导问题,后者是升级包/板端代码问题。本文把升级链路拆成四个环节逐一排查。
一次完整的 OTA/Recovery 升级,由四个环节组成:① recovery 镜像(迷你系统)→ ② misc 分区的引导指令(决定重启后进不进 recovery)→ ③ 板端升级代码(rkupdate,实现 Rockusb)→ ④ 升级包 update.img(打包了哪些分区)。逐环节确认,失败就能定位到具体一环。
1、升级链路全景

2、环节 ①:recovery 镜像从哪来
recovery 不是内核的一部分,而是 SDK 单独构建的一个极简 Buildroot 系统 + recovery 专用内核,最终打包成一个 FIT 镜像。构建入口是 device/rockchip/common/scripts/mk-recovery.sh:
用 RK_RECOVERY_CFG(本 SDK = rockchip_rk3576_recovery,对应 buildroot/configs/rockchip_rk3576_recovery_defconfig)编一个迷你 rootfs(initrd 为 cpio.gz);
编 recovery 专用内核(mk-kernel.sh recovery-kernel);
用 FIT 模板 device/rockchip/.chips/rk3576/boot4recovery.its 把 fdt + kernel + ramdisk + resource 打成一个 recovery.img。
排障点:烧录前先确认 output/firmware/recovery.img 存在且是最近一次 ./build.sh recovery 的产物。recovery 分区在 parameter 里固定为 128MB(见下),镜像别超。
3、环节 ②:怎么进 recovery——misc 分区的秘密
重启后会不会进 recovery,由 misc 分区的内容决定。device/rockchip/common/scripts/mk-misc.sh 生成 misc.img:
misc.img 只有 48KB(truncate -s 48k),分区本身是 4MB;
若配置 RK_MISC_RECOVERY,会在 偏移 16KB 写入 "boot-recovery",偏移 16KB+64 写入 recoveryn<参数>——bootloader 读 misc 看到这些指令就会进 recovery;
若配置 RK_MISC_BLANK,生成的是空白 misc——重启直接进正常系统。
排障点:本 SDK 默认 RK_MISC_BLANK=y(见 output/final.env)。所以"重启直接进 recovery"对烧入的固件不生效是正常的——要么用系统里的 reboot recovery 指令(由升级脚本写 misc),要么在 recovery 模式下按组合键/用升级工具。
4、环节 ③:板端升级代码 rkupdate
进入 recovery 后,真正"刷分区"的是 external/rkupdate ——一套在板端实现 Rockusb 协议的 C++ 代码(RKComm.cpp 管 USB 通信、Upgrade.cpp 管升级流程、RKDevice.cpp 管设备枚举)。它的 main.cpp 会把进度通过管道回传给 recovery 界面:ui_print <文本>、set_progress / progress。
排障点:U 盘升级/ADB 侧载失败时,看板端日志里 rkupdate 是否启动、Rockusb 枚举是否成功、进度回调是否在走;卡住往往是 USB 枚举或镜像读取问题。
5、环节 ④:升级包 update.img
device/rockchip/common/scripts/mk-updateimg.sh 用 tools/linux/Linux_Pack_Firmware/rockdev 打包 update.img。它先读 parameter.txt 生成 package-file(每行一个"分区 → 镜像"),然后按分区逐个打进去:parameter / bootloader / uboot / trust / boot / recovery / misc / oem / userdata / rootfs。
A/B 分区 :对 system_a/system_b 这类分区,打包 ab-ota 类型时跳过 _b 分区(backup 分区标记为 RESERVED 不打)。
OTA 开关 :SDK 配置 RK_UPDATE=y、RK_OTA_PACKAGE_FILE_DEFAULT=y。
排障点:"OTA 刷不上"先查升级包本身:用 upgrade_tool SFI update.img 看固件信息、分区是否与目标 parameter 一致;A/B 升级看槽位切换(misc/bootloader_message)是否正确。
6、排障对照表
| 现象 | 故障环节 | 处理 |
|---|---|---|
| 重启后直接进正常系统,不进 recovery | ② misc | 本 SDK 默认 misc 为空(RK_MISC_BLANK=y);用 reboot recovery 或强制键进入,而非烧入固件自带 |
| recovery 卡黑屏 / 起不来 | ① recovery.img | 重新 ./build.sh recovery 并确认 recovery.img 已烧录;检查 recovery 分区容量是否够(128MB) |
| OTA 刷到一半失败 / 进度不动 | ③ rkupdate / ④ 升级包 | 看板端 rkupdate 日志;用 SFI 检查升级包、对比分区表 |
| 提示分区不匹配 / 空间不足 | ④ 升级包 vs parameter | 用同一 parameter 重新打 update.img;A/B 场景检查 _a/_b 槽位 |
升级失败按链路定位:进不去 recovery → 查 recovery.img 是否构建/烧录、misc 引导指令(boot-recovery)是否写入、是否用 reboot recovery;OTA 刷不上 → 查板端 rkupdate 是否跑通 Rockusb、升级包分区与目标 parameter 是否匹配。两个问题,四个环节,逐个排除即可。
四、分区改了不生效、系统空间不够用?
parameter.txt 是分区布局的唯一真相。改了"没反应"、想扩容"加不进"——基本都是没理解它怎么被消费,以及 rootfs:grow 是怎么吃掉剩余空间的。
parameter.txt 是构建/烧录/打包三处的共同输入:修改后要同时让三处生效——① 重新构建镜像 → ② 重新烧录 parameter 分区 → ③ 重新打包 update.img。只改文件不重烧,当然"不生效"。另外,rootfs 是 grow 分区(吃掉所有剩余空间),想给某个分区扩容,必须同时缩小别的分区,否则空间"加不进去"。
1、parameter.txt 逐字段拆解
本 SDK 的默认分区表在 device/rockchip/.chips/rk3576/parameter.txt,实际内容如下:
FIRMWARE_VER: 1.0MACHINE_MODEL: RK3576MACHINE_ID: 007MANUFACTURER: RK3576MAGIC: 0x5041524BATAG: 0x00200800MACHINE: 0xffffffffCHECK_MASK: 0x80PWR_HLD: 0,0,A,0,1TYPE: GPTGROW_ALIGN: 0CMDLINE: mtdparts=:0x00002000@0x00004000(uboot),0x00002000@0x00006000(misc),0x00020000@0x00008000(boot),0x00040000@0x00028000(recovery),0x00010000@0x00068000(backup),0x01400000@0x00078000(userdata),0x00040000@0x01478000(oem),-@0x014B8000(rootfs:grow)uuid:rootfs=614e0000-0000-4b53-8000-1d28000054a9uuid:boot=7A3F0000-0000-446A-8000-702F00006273
关键点:
分区布局写在 CMDLINE: mtdparts= 这一行 。构建脚本 partition-helper 就是 grep "^CMDLINE:" 后解析这一行来生成分区表的。
分区格式 0x大小@0x偏移(名字)(@ 前是大小、@ 后是偏移),单位是扇区(512B)。
最后一个分区写 - 表示"无限/grow",占满剩余空间——这就是 rootfs。
uuid:boot / uuid:rootfs 给 boot/rootfs 固定 UUID(fstab、内核挂载依赖它)。
2、默认分区换算表(扇区 → 实际大小)
| 分区 | 大小(扇区) | 实际大小 |
|---|---|---|
| uboot / misc | 0x2000 | 4MB |
| boot | 0x20000 | 64MB |
| recovery | 0x40000 | 128MB |
| backup | 0x10000 | 32MB |
| userdata | 0x1400000 | 约 10GB |
| oem | 0x40000 | 128MB |
| rootfs | -(grow) | 剩余全部空间 |
换算:扇区数 × 512 = 字节。SDK 自带换算函数 rk_partition_size_readable_to_sector()(支持 K/M/G/0x 与 grow)在 partition-helper 里。
3、改分区的三种姿势
| 方式 | 说明 |
|---|---|
| 手改 parameter.txt | 最直接,但改 CMDLINE: 行时容易把 offset 改乱,建议只在调整已有分区大小时用 |
| ./build.sh mod-parts | 交互式编辑器(mk-partitions.sh):支持 print-parts / edit-parts / new-parts / insert-part / del-part / move-part / rename-part / resize-part,自动重排 offset 并写回 parameter.txt,推荐 |
| Windows ParameterTool | 图形工具 tools/windows/ParameterTool_v1.2/,可视化编辑,适合量产前统一配置 |
4、"改了不生效"的根因对照表
| 现象 | 根因 | 处理 |
|---|---|---|
| 改了参数文件,烧进去没变化 | 只改了源文件,没重新构建/没烧 parameter 分区 | 重新 ./build.sh 后烧 rkflash.sh all(含 di -p parameter.txt),或 rkflash.sh parameter |
| 分区错乱 / 引导起不来 | 手改 CMDLINE 时 offset 没跟着推,分区重叠或断档 | 用 mod-parts 自动重排;改前先 print-parts 看当前布局 |
| 想扩容 rootfs 却加不进去 | rootfs 是 -@...(...grow),只占"剩余空间";其它分区固定后剩余就那么多 | 先缩小固定分区(如 userdata 10GB、oem 128MB),rootfs 自动变大 |
| 新增分区后挂载不上 / 镜像打不进去 | update.img 打包按"分区名找同名镜像"(mk-updateimg.sh);挂载按 PARTLABEL | 新增分区要同名镜像 + 挂载配置(RK_EXTRA_PARTITION_* / fstab) |
| rootfs 挂载失败 / 找不到 | 动了 uuid:rootfs / uuid:boot | 保留/同步 UUID;内核与 fstab 按 UUID 挂载 |
5、实操:给 rootfs 扩容(示例思路)
# 1. 看当前布局./build.sh print-parts# 2. 进入交互式修改:把 userdata 从 0x1400000 调小(如 8GB)./build.sh mod-parts> resize-part userdata 8G> print-parts # 确认 rootfs 变大> done# 3. 重新构建并烧录 parameter 分区./build.sh./rkflash.sh parameter # 或全量 rkflash.sh all# 4. 验证df -h / # 看 rootfs 实际大小lsblk # 看分区表
分区不生效 = 没让"重新构建 + 重烧 parameter + 重打镜像"三件事同步生效;空间加不进去 = 忘了 rootfs 是 grow 分区,先要给固定分区让路。改分区用 mod-parts 自动维护 offset,最稳。
五、板子卡在开机画面,怎么用串口日志确定卡在哪?
卡在开机画面 ≠ 卡在内核。把启动拆成"内核 → rootfs → init"三段,看最后一条日志停在哪个阶段的哪个标志位,就能精确定位。
串口日志是启动过程的"进度条"。判断卡点就一句话:日志最后停在哪个"阶段标志"附近,问题就在那一段。本文给你三段的标志性日志与常见卡点对照表。
边界说明:U-Boot 到 "Starting kernel ..." 之前的启动段属引导加载器问题,本系列不讲(见 uboot-series 06)。本文从内核早期日志开始。
1、先确认串口能看到内核日志
RK3576 的调试串口与内核 console 由设备树 chosen 节点决定。本 SDK 的板级 bootargs(kernel-6.1/arch/arm64/boot/dts/rockchip/rk3576-linux.dtsi):
chosen: chosen { bootargs = "earlycon=uart8250,mmio32,0x2ad40000 console=ttyFIQ0 root=PARTUUID=614e0000-0000 rw rootwait rcupdate.rcu_expedited=1 rcu_nocbs=all";};
earlycon=uart8250,mmio32,0x2ad40000:内核早期日志输出口;
console=ttyFIQ0:正式 console(FIQ 调试口);
root=PARTUUID=614e0000-0000:rootfs 按 PARTUUID 挂载——正是 parameter.txt 里 uuid:rootfs=614e0000-0000-...(见 01.04)。
串口要能看到完整日志,需要 CONFIG_SERIAL_8250_CONSOLE=y(defconfig 已开)并且波特率与 U-Boot 串口一致。
2、三段切分法:找"阶段标志日志"
| 阶段 | 标志性日志(正常顺序) | 含义 |
|---|---|---|
| 内核早期 | Booting Linux on physical CPU 0x0000000000 [0x412fd050]、Kernel command line: ... | 内核已接管,开始打印启动参数(能确认 bootargs 是否生效) |
| 内核驱动 | 一串 [ 秒.微秒 ] ... 带时间戳的 probe 日志(本内核开了 CONFIG_PRINTK_TIME=y,时间戳来自 ARM 架构定时器) | 驱动初始化;日志停在哪条附近=那个驱动/子系统卡住 |
| rootfs | VFS: Mounted root (ext4 filesystem) ...、Run /sbin/init as init process | 根文件系统挂载成功、即将启动 init——rootfs 没问题的最强信号 |
| init/系统 | systemd 相关:[ OK ] Started ...、Reached target Multi-User System(Debian/Bookworm 用 systemd) | 用户态系统起来了;卡在这里=应用/服务/桌面问题 |
3、常见卡点对照表
| 日志尾部特征 | 卡点 | 处理方向 |
|---|---|---|
| 没有日志 / 只有 U-Boot 后无输出 | 内核早期 | 确认 earlycon 参数与串口波特率;确认 dtb 是否真的加载到该板型 |
| 停在某个驱动 probe 后(时间戳不再前进) | 内核驱动 | 看最后打印的驱动名,检查其 dts 节点/时钟/IO 域(见 02.04/02.05) |
| Kernel panic - not syncing: VFS: Unable to mount root fs | rootfs | root=PARTUUID 与 parameter 的 uuid:rootfs 是否一致;rootfs 镜像是否完整(见 01.04) |
| 出现 Run /sbin/init 后无后续 | init/系统 | systemd 卡住:进 recovery 模式 / 单用户模式看 journal(systemctl status、journalctl -b) |
| 画面有 logo 但无任何日志 | 非串口路径 | 可能串口没接对/波特率错,或日志级别过低——先解决"看得到日志"再谈定位 |
4、实操:抓一份能定位的日志
# 1. 串口工具(minicom/picocom)连调试串口,把完整启动日志存到文件# 波特率要与 U-Boot/内核一致(RK3576 默认调试串口,通常 1500000)# 2. 复现一次开机,保存日志# 3. 本地确认三段标志是否出现grep -E "Booting Linux|Kernel command line" boot.log # 内核接管grep -E "VFS: Mounted root|Run /sbin/init" boot.log # rootfs 就绪tail -50 boot.log # 看卡死前最后 50 行# 4. 能进系统但慢/卡:用 dmesg 看本次启动dmesg | grep -iE "error|fail|panic" | head
卡在开机画面时:
① 保证能看到内核日志(earlycon/console、波特率);
② 看日志尾部的阶段标志——Run /sbin/init 之前卡住是内核/rootfs 问题,之后卡住是 init/系统问题;
③ rootfs 卡死先核对 root=PARTUUID 与 parameter 的 uuid:rootfs 是否一致。
审核编辑 黄宇
全部0条评论
快来发表一下你的评论吧 !