Skip to content

K3 严格冷启动直接进入 StarryOS ​

之前我们的稳定流程一直是:

text
K3 上电
→ 先启动 Bianbu Linux
→ 完成 RCPU / RPMI 等平台初始化
→ warm reboot
→ FORCE_RECOVERY
→ Debug FSBL
→ OpenSBI
→ U-Boot
→ StarryOS

也就是说,之前一直认为 必须先启动一次官方 Bianbu Linux,让板子内部的一些管理模块进入正确状态,然后再 warm reboot,Debug 启动链才能稳定工作。

这个流程虽然能用,但比较麻烦,而且老师这次也明确提出,希望解决两个问题:

  1. K3 能不能真正从冷启动直接进入 StarryOS;
  2. 后面能不能把现在这一大串人工操作自动化。

所以这一阶段首先重新检查了第一个问题。

1. 之前为什么怀疑冷启动有问题 ​

历史实验里曾经出现过一次比较典型的失败:

text
BootROM
→ Debug FSBL
→ OpenSBI
→ 没有进入 Full U-Boot

当时通过 JTAG 抓到 CPU 位于 OpenSBI 的:

text
csi_dcache_invalid_range()
__smq_rx()

后来继续分析发现,这里实际上属于 RPMI shared-memory mailbox 的接收流程。

RPMI 可以简单理解成:

AP 主 CPU 和 RCPU 管理核之间用来交换电源、时钟、HSM 等平台管理消息的一套通信协议。

OpenSBI 会通过共享内存向 RCPU 发请求,然后等待 RCPU 返回 ACK。

进一步检查历史现场后发现,当时 P2A_ACK 接收队列的:

text
head = 0x10000000
tail = 0x00040300

都是非法值。

而正常队列只有 14 个 slot,因此合法范围应该是:

text
0 ~ 13

这说明历史失败现场的 RPMI shared memory 确实处于异常状态。

2. 把 OpenSBI 的 RPMI 初始化流程查清楚 ​

这一轮又继续把 OpenSBI 源码里的调用关系完整追了一遍。

目前已经确认,K3 OpenSBI 启动时最早的一条 RPMI 请求是:

text
Base Service Group
Service ID = 0x06
Probe Service Group

通过:

text
A2P_REQ

发送,再从:

text
P2A_ACK

等待响应。

默认接收超时是 20 ms。

一开始我们以为,如果 RCPU 没有响应,这里可能会直接把 OpenSBI 卡死。

但源码继续往上追以后发现并不是这样。

实际错误传播大概是:

text
RPMI 请求超时
→ rpmi_shmem_mbox_init() 返回 timeout
→ RPMI HSM 初始化失败
→ fdt_hsm_init() 忽略这个错误
→ OpenSBI 继续启动
→ Full U-Boot

也就是说,RPMI/HSM 在这里属于一种可选的平台管理能力,初始化失败并不会阻止当前启动 hart 继续进入 U-Boot。

这也解释了一个之前一直觉得矛盾的问题:

text
Debug FIT 明明没有 ESOS / RCPU firmware
为什么冷启动还是有可能进入 Full U-Boot?

答案是:

进入 Full U-Boot 本身并不能证明 RPMI 或 RCPU 正常。

OpenSBI 可以在 RPMI 初始化失败后继续运行。

3. Debug Golden Flow 并不会偷偷加载 ESOS ​

为了确认是不是 Debug FSBL 又从 QSPI 的 esos 分区偷偷加载了 RCPU firmware,这次也专门把 SPL 的加载流程查了一遍。

结果比较明确:

USB Recovery 模式下:

text
BootROM
→ FSBL
→ BOOT_DEVICE_BOARD
→ fastboot 下载 combined FIT

而 board_load_extra_fits() 没有 BOOT_DEVICE_BOARD 对应的 ESOS 加载分支。

同时冻结的:

text
k3-jtag-ram-opensbi-uboot.itb

里面只有:

text
OpenSBI
U-Boot
DTB

没有:

text
rcpu0-fw
rcpu1-fw
ESOS

所以当前 Debug Golden Flow 本身不会重新执行 rproc_load() / rproc_start() 去启动 RCPU。

这一步也让整个启动链的理解更清楚了:

text
能启动 U-Boot
≠
RPMI 正常
≠
RCPU / ESOS 正常

以前这几个概念有点混在一起,现在已经拆开了。

4. 重新进行了真正的 Strict Cold 实验 ​

为了排除之前 warm boot 状态残留的影响,这次重新设计了比较严格的冷启动实验。

断电时同时断开:

text
K3 主电源
USB Download
J-Link
CH340 USB

CH340 与板子只连接:

text
TX
RX
GND

没有连接 3.3V / 5V / VCC。

完全断电等待以后,再从:

text
FORCE_RECOVERY
→ BootROM USB Recovery

重新开始。

BootROM 状态确认:

text
version-brom: 1.0

随后重新上传 Debug FSBL:

text
BootROM
→ FSBL

SPL 正常出现:

text
U-Boot SPL 2022.10-dirty
DDR training consume ...
Debug JTAG enabled on MMC1 pins

然后继续上传:

text
k3-jtag-ram-opensbi-uboot.itb

最终成功出现:

text
U-Boot 2022.10-dirty
CPU: rv64imafdcvh
Model: spacemit k3 com260 ifx board
DRAM: 8 GiB

也就是说:

text
严格冷启动
→ Debug FSBL
→ OpenSBI
→ Full U-Boot

已经能够直接成功。

而且这个实验后面又重新重复了一次,在完全不接 JTAG、不使用 GDB 干扰启动的情况下,结果仍然成功。

因此以前的:

text
必须先启动 Bianbu
→ warm reboot
→ 才能 Debug 启动

已经不能继续作为固定前置条件。

目前更准确的结论应该是:

历史上确实发生过 cold direct-Recovery 下的异常,但它不是一个稳定必现条件。

5. Strict Cold 下 UFS 也成功了 ​

进入 Full U-Boot 以后,继续执行:

text
scsi scan

这一步是让 U-Boot 初始化 K3 的 UFS 控制器,并扫描实际的存储设备。

结果成功识别:

text
Vendor: KINGSTON
Prod.: TY7B-128
Capacity: 119.2 GB

说明在这次真正的冷启动条件下:

text
K3 UFS
→ MPHY
→ Host Controller
→ Device Scan

也是能够正常工作的。

这一步很关键,因为 StarryOS 的 rootfs 最终还是需要从这块 UFS 上读取。

6. 冷启动直接进入 StarryOS ​

随后按照已经冻结的 Host-DWARF 启动方式,把 StarryOS kernel 下载到:

text
0x140000000

对应文件:

text
starryos_host_dwarf_release.bin

然后把 DTB 下载到:

text
0x138000000

对应文件:

text
spacemit-k3-com260-ifx.dtb

最后执行:

text
booti 0x140000000 - 0x138000000

这一套仍然是我们之前已经验证过的 StarryOS 人工启动方式。

最终串口成功出现:

text
Welcome to Starry OS!

因此这一次已经实际完成:

text
完全断电
↓
BootROM Recovery
↓
Debug FSBL / SPL
↓
OpenSBI
↓
Full U-Boot
↓
UFS / KINGSTON
↓
Host-DWARF StarryOS
↓
Welcome to Starry OS!

而整个过程:

text
没有先启动 Bianbu
没有 warm reboot
没有依赖 Linux 做前置初始化

7. 这次结果意味着什么 ​

这一阶段最大的变化,其实不是又多跑通了一次 StarryOS,而是我们把之前对冷启动问题的理解修正了。

以前的理解比较像:

text
cold boot
→ RCPU/RPMI 没准备好
→ OpenSBI 卡死
→ 必须 Bianbu warm boot

现在应该改成:

text
历史 cold 异常
→ 曾经观察到 RPMI queue 状态异常
→ OpenSBI 当时正在 RPMI RX 重试
→ 但 RPMI timeout 本身不会阻止 OpenSBI继续
→ 历史失败还存在其他条件性因素

与此同时:

text
Strict cold
→ Debug Golden Flow
→ Full U-Boot
→ UFS
→ StarryOS

已经被真板实际验证。

所以从当前工程目标来看:

“先启动 Bianbu 再 warm reboot”已经可以从 StarryOS Debug Golden Flow 的必需步骤中删除。

至于 RCPU / RPMI 在 strict cold 下到底有没有完整工作,目前仍然没有完全证明。

这件事和“StarryOS能不能直接冷启动”现在已经可以拆成两个问题:

text
问题 A:
Cold → StarryOS
目前已经验证成功。

问题 B:
Cold → RCPU / ESOS / RPMI 完整平台管理能力
仍需要后续单独验证。

这样就不会再因为 RPMI问题,把整个 StarryOS启动链一起判定为失败。

8. 下一阶段 ​

老师提出的第一个目标:

K3 真正冷启动直接进入 StarryOS。

目前已经基本完成。

接下来可以开始第二个目标:

把现在繁琐的人工 Golden Flow 自动化。

现在人工流程已经非常明确:

text
BootROM Recovery
→ 上传 FSBL
→ 等待 SPL
→ 上传 OpenSBI + U-Boot FIT
→ 等待 Full U-Boot
→ scsi scan
→ 上传 StarryOS kernel
→ 上传 DTB
→ booti
→ 等待 StarryOS ready

现有脚本虽然已经能封装部分 Host 侧 fastboot 命令,但很多步骤仍然需要人工:

text
看串口
按 Enter
输入 scsi scan
启动 U-Boot fastboot
输入 booti
人工判断是否成功

所以接下来计划把它改成一个真正的状态驱动启动流程:

text
检测 BootROM
↓
自动识别 SPL ready
↓
自动识别 Full U-Boot ready
↓
自动执行 UFS 初始化
↓
自动加载 kernel / DTB
↓
自动执行 booti
↓
自动等待 Welcome to Starry OS!

这里的核心是让脚本根据板子的真实串口状态决定下一步。

这样以后 K3 + StarryOS + ARD 的日常调试,就可以从现在这种比较长的人工操作,逐步变成真正稳定的一键启动流程。