在嵌入式系统开发领域,双系统启动(AB系统)已经成为提升设备可靠性和实现无缝升级的关键技术方案。RK3588作为瑞芯微新一代旗舰级处理器,其强大的硬件性能和灵活的启动架构为双系统实现提供了理想平台。作为一名长期深耕嵌入式开发的工程师,我在最近的项目中完整实现了RK3588平台的AB双系统支持,本文将重点分享UBOOT层面的改造经验以及完整的编译实践。
AB系统方案的核心价值在于:
RK3588采用典型的嵌入式启动链:
code复制ROM Code → Loader → U-Boot → Kernel → Rootfs
AB系统的特殊之处在于UBOOT阶段需要增加系统选择逻辑,并在内核启动参数中传递正确的rootfs分区信息。
典型的AB系统分区布局示例(eMMC 32GB):
| 分区名称 | 大小 | 用途说明 |
|---|---|---|
| boot_a | 64MB | A系统内核和设备树 |
| boot_b | 64MB | B系统内核和设备树 |
| system_a | 2GB | A系统根文件系统 |
| system_b | 2GB | B系统根文件系统 |
| vendor | 512MB | 公共驱动和固件 |
| userdata | 剩余空间 | 用户数据分区 |
注意:实际分区大小需要根据具体应用场景调整,系统分区建议保留至少20%的冗余空间
实现AB系统需要在UBOOT中增加以下功能:
建议使用官方推荐的开发环境:
bash复制sudo apt-get install git-core gnupg flex bison build-essential zip \
curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev \
x11proto-core-dev libx11-dev lib32z1-dev libgl1-mesa-dev libxml2-utils xsltproc unzip
获取RK3588官方UBOOT源码:
bash复制git clone https://github.com/rockchip-linux/u-boot.git -b master
cd u-boot
关键修改文件:
include/configs/rk3588_common.h - 添加AB系统相关配置宏common/cmd_bootrk.c - 实现系统选择逻辑drivers/mmc/rkmmc.c - 增加分区状态检测功能核心代码片段示例(系统选择逻辑):
c复制int select_boot_slot(void) {
char *slot_suffix = NULL;
int ret;
ret = get_boot_slot(&slot_suffix);
if (ret) {
printf("Fallback to default slot\n");
slot_suffix = "_a"; // 默认启动A系统
}
env_set("bootargs",
format_bootargs(env_get("bootargs"), slot_suffix));
return 0;
}
编译配置命令:
bash复制make CROSS_COMPILE=aarch64-linux-gnu- rk3588_defconfig
make menuconfig
需要特别关注的配置项:
code复制CONFIG_ROCKCHIP_AB_SYSTEM=y
CONFIG_ROCKCHIP_BOOT_SLOT_SELECT=y
CONFIG_ROCKCHIP_FIT_IMAGE=y
CONFIG_ROCKCHIP_AVB_LIBAVB=y
完整编译命令:
bash复制make CROSS_COMPILE=aarch64-linux-gnu- -j$(nproc)
生成的关键文件:
u-boot.bin:主二进制文件u-boot-rockchip.bin:Rockchip格式镜像u-boot.itb:包含设备树的镜像烧录工具推荐使用RKDevTool,关键步骤:
u-boot-rockchip.bin0x200000(2MB位置)现象:设备在UBOOT阶段不断重启
排查步骤:
bootargs是否正确设置bootcmd是否包含不兼容的命令典型解决方案:
bash复制# 在UBOOT命令行中尝试
env set bootcmd "mmc dev 0; ext4load mmc 0:1 0x800800 boot.img; bootm 0x800800"
env save
reset
可能原因:
修复方法:
bash复制# 强制切换到B系统
mmc dev 0
mmc partconf 0 1 1 1
setenv boot_slot _b
saveenv
reset
常见编译错误及解决方法:
| 错误类型 | 解决方案 |
|---|---|
| 工具链不兼容 | 确认使用aarch64-linux-gnu-前缀的工具链,版本建议gcc-linaro-7.5.0 |
| 依赖缺失 | 运行scripts/checkpatch.pl检查缺失依赖 |
| 设备树编译失败 | 检查arch/arm/dts/rk3588-xxx.dts是否存在语法错误 |
| 镜像大小超出限制 | 修改CONFIG_SYS_MALLOC_LEN和CONFIG_SYS_BOOTM_LEN增加内存分配空间 |
实测数据对比(RK3588 @ 2.4GHz):
| 优化措施 | 启动时间(ms) | 效果提升 |
|---|---|---|
| 默认配置 | 1200 | - |
| 启用CONFIG_SPL_DM | 980 | 18.3% |
| 使用FIT镜像 | 850 | 29.2% |
| 预加载环境变量 | 720 | 40% |
关键配置:
makefile复制CONFIG_SPL_DM=y
CONFIG_FIT=y
CONFIG_ENV_IS_NOWHERE=y
建议的安全配置:
makefile复制CONFIG_RK_CRYPTO=y
CONFIG_RK_SECURE_BOOT=y
bash复制openssl genrsa -out private.pem 2048
tools/rk_sign_tool sign --key private.pem --sha256 u-boot.bin
c复制#define CONFIG_ROCKCHIP_ANTI_ROLLBACK 1
#define CONFIG_ROCKCHIP_AVB_VERSION 2
高级调试方法:
bash复制openocd -f interface/jlink.cfg -f target/rk3588.cfg
bash复制md.b 0x1000000 0x100 # 查看内存内容
bash复制fdt addr ${fdt_addr_r}
fdt resize 8192
fdt set /serial@ff130000 status "okay"
在实际项目中,我们实现了以下关键指标:
几个重要的经验教训:
这个方案目前已经稳定运行在工业控制设备上超过6个月,经历了各种异常断电测试的考验。对于想要实现类似功能的开发者,我的建议是从小规模测试开始,逐步验证每个功能模块,特别注意异常处理流程的完备性。