Appearance
K3 严格冷启动直接进入 StarryOS
之前我们的稳定流程一直是:
text
K3 上电
→ 先启动 Bianbu Linux
→ 完成 RCPU / RPMI 等平台初始化
→ warm reboot
→ FORCE_RECOVERY
→ Debug FSBL
→ OpenSBI
→ U-Boot
→ StarryOS也就是说,之前一直认为 必须先启动一次官方 Bianbu Linux,让板子内部的一些管理模块进入正确状态,然后再 warm reboot,Debug 启动链才能稳定工作。
这个流程虽然能用,但比较麻烦,而且老师这次也明确提出,希望解决两个问题:
- K3 能不能真正从冷启动直接进入 StarryOS;
- 后面能不能把现在这一大串人工操作自动化。
所以这一阶段首先重新检查了第一个问题。
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 USBCH340 与板子只连接:
text
TX
RX
GND没有连接 3.3V / 5V / VCC。
完全断电等待以后,再从:
text
FORCE_RECOVERY
→ BootROM USB Recovery重新开始。
BootROM 状态确认:
text
version-brom: 1.0随后重新上传 Debug FSBL:
text
BootROM
→ FSBLSPL 正常出现:
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 的日常调试,就可以从现在这种比较长的人工操作,逐步变成真正稳定的一键启动流程。