Ch1 — 引导启动:主线 7.1 真机首启到 login
这一章把 RK3568 ATK 板从 BootROM 一路跑到 busybox 的
login:。和 RK3588 那条启动链比,RK3568 的前段简单一截——vendor 的rk356x_spl没有 RK3588 那个基址错配的 bootloop,不需要切主线 SPL,所以咱们这章不花篇幅在「让 BL31 进场」上,而是把力气花在 eMMC 启动这条路的几个板级细节上。完整记录见 notes/40。
先说清楚范围:这一章讲的是 MVP 首启——用主线自带的
rk3568-evb1-v10.dtb(主线 EVB1 的 DT,ATK 板是它的变体)跑通启动链。ATK 板级设备树那八个子系统(PMIC、双 GMAC、audio、触摸、LCD、CAN、RTC、WiFi)的移植是 下一章 的事,本章不碰。
启动链长什么样
RK3568 的启动链画出来是这样:
BootROM
→ DDR init ← rkbin 闭源 blob(1560 MHz, 4 GiB)
→ idbloader @0x40 ← binman 自产(主线),不再是 vendor 的 loader
→ SPL ← vendor rk356x_spl v1.14(rkbin blob,这条板能用)
→ ATF BL31 ← rkbin v1.46(OP-TEE 省略,无害 warning)
→ U-Boot 2026.07-rc4 ← 主线,evb1-v10 DT
→ bootm FIT ← kernel + DTB
→ Linux 7.1.0 ← 主线 v7.1,SMP PREEMPT,4 × Cortex-A55
→ mmc1 HS200 eMMC ← mmcblk1, p1/p2/p3
→ EXT4 → busybox init → login和 RK3506B 比,RK3568 多了 ATF BL31 这一级(ARMv8-A 必需);和 RK3588 比,RK3568 的 vendor SPL 跟 BL31 没有基址冲突,所以这一级可以继续借 vendor blob,不用像 RK3588 启动章 那样切主线 SPL。
这一章值得记的一个工程进步是 idbloader 由 binman 自产——也就是说 loader 这段不再依赖 vendor 的打包工具,binman 直接从主线 U-Boot 的构建产物 + rkbin 的 DDR/usbplug blob 组出 idblock。这是 RK3568 移植一开始就立起来的「零 vendor 打包工具」基线,后面 RK3588 沿用了同一条路。
eMMC 这条启动路的分区是 GPT 三段:p1 放 u-boot、p2 是 boot 分区(放 boot.img / FIT)、p3 是 rootfs(ext4)。boot.scr 放在 rootfs 分区的 /boot/ 下——这个位置选择是有讲究的,见下面第一个坑。
坑之一:bootflow 找不到 raw FIT,boot.scr 要放 rootfs
U-Boot 默认 bootcmd=bootflow scan,让它自己扫启动设备。可 RK3568 的 eMMC boot 分区(p2)是裸 FIT(raw,没有文件系统),bootflow 在一个没有文件系统的分区上找不到入口,就卡住了。
正解是把 boot.scr 放在 rootfs 分区(p3)的 /boot/ 下。rootfs 是 ext4 有文件系统,U-Boot 的 SCRIPT bootmeth 能命中它、读出 boot.scr、source 执行。这相当于把「启动脚本入口」从 boot 分区挪到了 rootfs 分区,绕开 raw FIT 找不到入口的问题。
坑之二:FIT 读到 0x02000000 会和 kernel load 撞车
boot.scr 里要把 FIT 从 eMMC 读进内存。第一版的写法是:
mmc read ${kernel_addr_r} ... # ${kernel_addr_r} = 0x02000000bootm 报:
new format image overwritten根因是 FIT 里描述的 kernel load address 也是 0x02000000。bootm 解 FIT 时要把 kernel 解压/搬到它自己声明的 load address(0x02000000),可咱们恰恰把整个 FIT 读到了 0x02000000——bootm 一搬,就把 FIT 自己覆盖了。
正解是把 FIT 读到不和 kernel/fdt load address 冲突的空闲 DRAM。RK3568 上 kernel load 在 0x02000000、fdt 在 0x12000000,咱们把 FIT 读到 0x08000000(两者之间的空闲区),bootm 再把 kernel 搬到 0x02000000 就不会覆盖 FIT 了:
mmc read 0x08000000 0x6000 0x20000 # FIT 读到 0x08000000
bootm 0x08000000 # bootm 从这里解 FIT、把 kernel 搬到 0x02000000⚠️ 这种「FIT 暂存地址 ≠ kernel load address」的坑很隐蔽——
bootm报的new format image overwritten不直接说「地址撞了」,得知道 FIT 的 load 机制才看得懂。RK3588 那边也踩了同一个坑、用的同一个 0x08000000 解法,两板独立验证过。
坑之三:rootfs 分区装不下,要 resize
首启用的 buildroot rootfs 是 Phase 2a 的全功能栈(Qt6/Mesa/GStreamer 那一套),展开 451 MB。可板配置里的 rootfs 分区只给了 512 MiB(parameter 的 0x00100000 扇区),扣掉文件系统开销装不下。
正解是把 rootfs 分区扩到 1 GiB,两处一起改:
# board/rk3568-atk/parameter-emmc-atk.txt
0x00100000 → 0x00200000 # rootfs 分区 512 MiB → 1 GiB
# scripts/pack-emmc.sh(RK3568 路径)
ROOTFS_MIB 256 → 1024 # ext4 镜像大小坑之四:eMMC 是 dev 0,SD 才是 dev 1
U-Boot 里 mmc dev 选设备,这个编号容易搞反。RK3568 上 mmc@fe2b0000(sdmmc0,SD 卡槽)是 dev 1,mmc@fe310000(sdhci,eMMC)是 dev 0——eMMC 是 dev 0,不是 dev 1。咱们中途一度搞反,照着「SD 是 0」的惯性写 mmc dev 1,结果读的是 SD 卡不是 eMMC。判据是 rk3568.dtsi 里的控制器地址:sdmmc0 = dwmmc@fe2b0000、sdhci = sdhci@fe310000,U-Boot 的 dev 号按探测顺序给,eMMC(sdhci)先拿到 dev 0。
坑之五:bootflow 不扫 eMMC 分区,目前还是手动 boot
上面四个坑过了,板子能在 U-Boot 提示符下手动 boot 到 login——敲这一串就行:
mmc dev 0
mmc read 0x08000000 0x6000 0x20000
setenv bootargs console=ttyS2,115200 root=/dev/mmcblk1p3 rw rootwait
bootm 0x08000000注意 root 是 mmcblk1p3——RK3568 ATK 的 eMMC 在 kernel 里是 mmcblk1(RK3588 topeet 是 mmcblk0,两板不一样,照搬必踩 Waiting for root device)。
可一松手让它 autoboot,它又不动。根因和 RK3588 一样:U-Boot 的 bootflow scan 对 eMMC(dev 0)不扫分区,手动 mmc dev 0 它认,bootflow 偏不扫。RK3588 那边用 CONFIG_BOOTCOMMAND 写死成「直接 load mmc 0:3 boot.scr; source」绕开了(见 RK3588 autoboot 节);RK3568 这条自动化当时没收尾——上电还得在 U-Boot 里手动敲上面那串。这是已知尾巴,落 CONFIG_BOOTCOMMAND 的 patch 是后续。
成功长这样
五个坑都过了,update.img 烧 eMMC,上电手动 boot,串口 115200 看到:
...(DDR / BL31 / U-Boot banner,115200 干净)
U-Boot 2026.07-rc4-00043 (evb1-v10 DT)
=> mmc dev 0
=> mmc read 0x08000000 0x6000 0x20000
=> setenv bootargs console=ttyS2,115200 root=/dev/mmcblk1p3 rw rootwait
=> bootm 0x08000000
...(Linux 7.1.0 SMP PREEMPT,4 × Cortex-A55)
mmc1: mmcblk1: p1 p2 p3 # eMMC HS200,注意是 mmcblk1
EXT4-fs (mmcblk1p3): mounted ...
...(busybox init)
rk3568 login: # 到 login,首启完成这一段从 notes/40 的真机记录里来的。到这一步,RK3568 主线启动链通了。
这里得区分「首启当时」和「交接时」两个状态,别把首启的临时毛病当成 RK3568 的最终能力。首启那天(notes/40)确实一堆问题:网络只有 lo(
STMMAC_ETH编成模块、rootfs 没装没 modprobe)、Qt6 没进 rootfs(tar 还是 Qt5 时期)、LCD 不亮(evb1-v10 DT 用raydium,rm67200,ATK 屏要另移植 panel)、GPU/VPU/USB3 deferred probe。可这些都是首启当天的快照——随后一轮大重 build(notes/41–42)把绝大多数都修通并板验了:STMMAC_ETH等改=y后 eth0/eth1 双口通(2× RTL8211F RGMII)、ATK panel 驱动移植后 LCD 点亮(card0-DSI-1 connected)、Panfrost Mali-G52 起来(card1)、Goodix GT928 触摸、CAN1、RTC pcf8563 全部板上验证通过。到交接时(notes/42)真正没收尾的只剩两个:音频 RK809(hp-det GPIO 抢了 i2s1 mclk、声卡没 probe,只有 BT SCO)和 WiFi rtl8852bs(SDIO 总线通、主线无驱动,待搬 vendor 851 文件驱动)。这些后续移植的板级 DT 当前还是 working-tree delta,等 patch 化(P4)落定后课程化成 下一章 及之后的章节。