场景:要在 RK3588 上做 **A 核 Linux + 实时域 Zephyr** 的异构开发——内核、设备树、guest 镜像、内核模块四类产物天天改, 而每一次改动都可能让板子起不来、或起来但门铃不响。这种活儿最容易的失败方式不是写错代码,而是把板子试挂了却回不去。 所以这套环境的核心不是「能跑 AMP」,而是:实验怎么试、失败怎么回、结论怎么证。
当前实测:Radxa ROCK 5B+(RK3588)· 内核 6.1.75-abdbg · 运行分支 debug(A/B 武装,abcount 自动记账)·
Zephyr guest 由 ATF 经厂商 rockchip,amp 路径在 A55 core3(MPIDR 0x300)启动
| 板卡 | Radxa ROCK 5B+(Rockchip RK3588):4×Cortex‑A76 + 4×Cortex‑A55,NPU 6 TOPS;eMMC 系统盘 + 2×NVMe 组 RAID1(/mnt/raid1,复位不丢的归档区) |
|---|---|
| Linux 侧 | Armbian(aarch64),内核 6.1.75-abdbg(自定义调试分支),厂商 AMP 支持;设备树经 /boot/debug/dtb/rockchip/ 加载 |
| Zephyr 侧 | 最小 Zephyr 镜像(zephyr-amp.bin),由 ATF 经厂商 rockchip,amp 路径在 A55 core3 上启动;A 核与实时域通过共享内存 + 门铃协作 |
| 启动/停止 guest | /sys/rk_amp/boot_cpu:echo on/off [cpu id] > /sys/rk_amp/boot_cpu,echo status [cpu id] 查状态。每次开机只有一次 CPU_ON 有效——想重试就重启 |
| 内核模块 | ndp_cons(控制台/门铃侧),必须在启动 guest 之前装载,否则 mailbox 被别的驱动先占 |
| 证据归档 | 板子 RAID 的 /mnt/raid1/shared/ab-boot-docs/:文档、日志、状态快照、脚本(INDEX.md 记录近 8000 个文件);ab-docs-sync 定时同步 |
板子有两条启动分支:stable(稳定产物)与 debug(实验产物)。所有实验只动 debug 分支,且由启动器自动记账回滚:
| 武装 / 回滚 | ab-ctl use-debug 武装实验分支 → reboot;ab-ctl use-stable 立即回稳定分支;touch /boot/ab-off 急停(持久禁用 debug) |
|---|---|
| 启动账本 | U-Boot 把本次启动的分支与计数写进 /proc/cmdline 的 absrc/abcount/abmax/ablast;abtag 打印分支证明 |
| 成功判定 | ab-boot-ok.service 在启动约 +75 s 记账、约 +199 s 判「健康」并清零 abcount;在此之前重启会被算作失败 |
| 自动回滚 | 连续失败 3 次(abmax=3)即自动切回 stable 并持久禁用 debug 分支——不需要人守着 |
| 失败演练 | ab-test-reboot.service(disabled 状态,只在演练回滚时临时开) |
| 为什么重要 | 内核/DTB 一改就可能起不来,而这块板子没有串口;自动回滚是唯一的「兜底通道」,也是敢每天做实验的前提 |
abcount 到 2 时再失败一次就自动回滚,先把根因想清楚再动手;
起来后先 abtag + ab-ctl status 核验,不对劲就 use-stable 回退再定位,不要在 debug 分支上连续试错。
| 内核 | 源码 /mnt/raid1/shared/linux-rockchip(需 CONFIG_ROCKCHIP_AMP=y)→ /boot/debug/{Image, System.map-*, vmlinux-*, uInitrd},重启生效 |
|---|---|
| 设备树 | arch/arm64/boot/dts/rockchip/rk3588-radxa-rock-5b+.dtb(源在 rk3588-radxa-rock-5b-ndp.dtsi,不改 blob)→ /boot/debug/dtb/rockchip/,重启生效 |
| Zephyr guest | zephyr_ndp/tests/amp_bringup → /boot/debug/zephyr-amp.bin,每次开机 echo "on 0x300" > /sys/rk_amp/boot_cpu 拉起 |
| ndp_cons 模块 | 就地 insmod,立即生效;必须在启动 guest 之前接管 fec60000.mailbox |
每类产物覆盖前都留 <文件>.pre-<tag>-<epoch> 备份——回退就是把备份改回原名,不需要重新构建。
而「部署生效」不用嘴说,用两把尺:
# 尺一:载入字节 == 文件(uio 只能 mmap,read() 只给中断计数) # 取 /dev/uio1 前 4 KiB 的 md5,与 /boot/debug/zephyr-amp.bin 同段 md5 比对 # 尺二:跑的代码 == 这一版(guest 自报 build id) cat /sys/module/ndp_cons/parameters/pcm | grep '^id:'
dd/cat 自证会得到假阴性;
启动脚本里载入 amp 镜像的那句 load … 失败不报错,所以「没换」永远静默——必须靠两把尺。
| 无串口 | 本机没有串口控制台:早期启动挂死不会自愈(系统看门狗只在 systemd 武装后生效,约 boot 12 s)。证据只能靠 /var/lib/ab-boot/history.log、ab-ctl journal、/var/lib/systemd/pstore/ |
|---|---|
| 非干净复位会丢写 | ext4 commit=120:拔电/硬复位会丢最近约 120 s 的写入。所以唯一一份源码与证据绝不放在 / 或 /home,母本必须在 RAID |
| AMP 在线时别跑重活 | 「AMP 数据面在线 + 重构建/重 I/O」已两次导致无现场复位(无 panic、无 pstore);空载跑 10 分钟不复现,AMP 不在线时构建也不复现。要做重活先停 guest 并重启 |
| 判定要满足前置 | 模块没装载时不能断言「数据面不动」;guest 没启动时不能断言「门铃不通」——先核验前置条件 |
| guest 每次开机只有一次机会 | CPU_ON 只有一次有效,guest 停掉后要重试只能重启板子 |
| 文档与代码目前是私有的 | 两个源码仓库与 RAID 文档都在工作组内部;需要账号或会员访问。本页只公开方法与边界 |
| 先分两条线 | ① 网络:本板走 WiFi,重启后 DHCP 可能要几分钟,期间 ping 与 22 都不通——别当挂死处理;② 真挂:journalctl --list-boots 多出启动、boot_id 变化 |
|---|---|
| 被自动回滚了? | 看 ab-ctl status 的 ablast 与 ab-ctl journal;回滚后 debug 分支被持久禁用,定位完再 use-debug 重新武装 |
| 起来了但门铃不响 | 先确认 ndp_cons 已装载、guest 已 status 为 on、中断线出现在 /proc/interrupts(rockchip-amp) |
文件全变 NUL / insmod 报 Invalid ELF header magic | 典型的非干净复位损坏:从 RAID 归档恢复母本,不要试图修补 |
west init/update 走国内源zephyrrtos_china/zephyr_ndp——NDP 模块 + tests/amp_bringup(Zephyr guest)zephyrrtos_china/linux-rockchip-rk3588-amp——本次工作所用的厂商内核源码/mnt/raid1/shared/ab-boot-docs/——runbook、契约、交接笔记与每次启动的账本