避坑指南:为香橙派Zero 3编译U-Boot时,BL31和Crust固件那些容易踩的坑
香橙派Zero 3 U-Boot编译实战:BL31与Crust固件疑难解析
当你在深夜的调试中看到串口终端突然跳出两遍U-Boot启动日志时,那种既兴奋又困惑的感觉,相信每个嵌入式开发者都深有体会。香橙派Zero 3作为全志H618平台的代表,其U-Boot编译过程中BL31和Crust固件的集成堪称"新人杀手"。本文将从实际故障现象出发,带你穿透表象理解底层机制,避开那些让开发者抓狂的典型陷阱。
1. 编译环境配置的隐形陷阱
交叉编译工具链的选择往往是最初的绊脚石。许多开发者会忽略全志H618芯片的双重特性——它既是Cortex-A53架构的64位处理器,又需要32位工具链处理AR100协处理器上的Crust固件。
1.1 工具链版本冲突
推荐使用以下组合:
# AArch64主处理器工具链
gcc-arm-11.2-2022.02-x86_64-aarch64-none-linux-gnu
# AR100协处理器工具链
or1k-linux-musl-cross
常见错误症状包括:
- BL31编译时报
illegal instruction - Crust固件链接阶段出现
unrecognized relocation警告 - U-Boot启动时卡在
Starting SCP...阶段
注意:切勿使用Ubuntu仓库中的默认交叉编译器,其缺少全志平台特定的指令集支持。
1.2 环境变量污染
.bashrc 中残留的旧版工具链路径会导致微妙的编译错误。建议创建隔离的编译环境:
mkdir -p ~/orangepi_build && cd ~/orangepi_build
cat > env_setup.sh <<'EOF'
export PATH="/opt/toolchains/aarch64-gcc/bin:/opt/toolchains/or1k-gcc/bin:$PATH"
export CROSS_COMPILE_AARCH64=aarch64-none-linux-gnu-
export CROSS_COMPILE_AR100=or1k-linux-musl-
EOF
source env_setup.sh
验证环境是否正确的快速方法:
aarch64-none-linux-gnu-gcc --version | grep 11.2
or1k-linux-musl-gcc --version | grep musl
2. BL31固件的配置玄机
全志H618与H616的关系就像孪生兄弟——硬件设计相似但存在关键差异。官方文档对此语焉不详,导致开发者常陷入平台选择的困境。
2.1 平台选择困境
在 arm-trusted-firmware/plat/allwinner 目录下,你会看到多个相似平台:
sun50i_h6/ # 原始H6平台
sun50i_h616/ # H616专用
sun50i_h618/ # 官方未提供
实际测试表明不同选项的表现差异:
| PLAT参数 | 启动成功率 | 内存初始化 | CPU频率识别 |
|---|---|---|---|
| sun50i_h6 | 60% | 不稳定 | 错误显示1.5GHz |
| sun50i_h616 | 95% | 稳定 | 正确显示1.8GHz |
| sun50i_a64 | 无法启动 | - | - |
最佳实践 :
make PLAT=sun50i_h616 DEBUG=1 bl31
2.2 调试符号的副作用
DEBUG=1参数在开发阶段很有用,但会产生两个隐患:
- 生成的BL31.bin体积过大(约800KB),可能超出引导区预留空间
- 串口输出过多调试信息干扰正常启动日志
建议发布版本移除DEBUG参数:
make PLAT=sun50i_h616 bl31
3. Crust固件的电源管理迷局
Crust作为全志特有的电源管理固件,其配置复杂度往往被低估。当系统出现以下症状时,很可能就是Crust在作祟:
- 无法正常关机(卡在
reboot: Power down) - 重启变成关机
- 系统唤醒后外设失效
3.1 配置文件选择策略
在 crust/configs 目录下,与H618最接近的配置是:
orangepi_3_defconfig # H6方案
orangepi_zero3_defconfig # 官方提供但存在缺陷
实测发现直接使用 orangepi_3_defconfig 反而更稳定。关键修改点:
# 修改crust/configs/orangepi_3_defconfig
-CONFIG_PSYCHO_CPU_VOLT=1100
+CONFIG_PSYCHO_CPU_VOLT=1200 # H618需要更高电压
3.2 编译时的线程陷阱
虽然多线程编译(make -j)能加快速度,但Crust编译系统对并行处理支持不佳。建议:
make orangepi_3_defconfig
make -j2 scp # 限制在2个线程以内
常见编译错误及解决方案:
-
错误1 :
or1k-linux-musl-ld: cannot find -lgloss解决方法:在Makefile中添加LDFLAGS += -nostdlib -
错误2 :
undefined reference to__stack_chk_guard'解决方法:禁用栈保护CFLAGS += -fno-stack-protector`
4. U-Boot集成时的典型故障
当BL31和Crust都编译成功后,集成到U-Boot阶段仍然可能遇到各种"灵异现象"。以下是几个最令人抓狂的案例:
4.1 双重启动之谜
串口输出中出现两遍U-Boot日志,通常表现为:
U-Boot SPL 2023.04
Trying to boot from MMC1
U-Boot SPL 2023.04
Trying to boot from MMC1
根本原因在于:
- SPL没有正确识别BL31加载状态
- 设备树中
/chosen节点冲突
解决方案分三步:
# 1. 修改include/configs/sunxi-common.h
-#define CONFIG_SPL_BOARD_LOAD_IMAGE
+#undef CONFIG_SPL_BOARD_LOAD_IMAGE
# 2. 更新设备树
&pmu {
status = "okay";
};
# 3. 重新编译时确保清除旧配置
make mrproper
4.2 环境变量传递失效
BL31参数无法正确传递给内核的表现:
- 内核启动时卡在
Starting kernel ... - 系统无法识别内存容量
- CPU频率显示异常
关键检查点:
-
确认BL31路径导出为绝对路径
export BL31=$(pwd)/arm-trusted-firmware/build/sun50i_h616/debug/bl31.bin -
验证U-Boot的
bootm命令是否包含bl31_phys_addr参数setenv bootargs 'earlyprintk console=ttyS0,115200 bl31_phys_addr=0x44000000' -
检查
.config中的关键选项:CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT=y CONFIG_ARMV8_PSCI=y
4.3 电源管理异常
当出现以下情况时,需要检查Crust集成:
- 按电源键无响应
- 系统无法唤醒
- 重启后外设初始化失败
调试步骤:
-
确认SCP路径导出正确
export SCP=$(pwd)/crust/build/scp/scp.bin -
在U-Boot中测试电源管理功能:
# 测试关机 pmic shutdown # 测试重启 pmic reboot -
必要时可临时禁用Crust:
export SCP=/dev/null
5. 烧录与调试实战技巧
当所有组件编译通过后,最后的烧录阶段仍然暗藏杀机。以下是从数十次失败中总结的宝贵经验。
5.1 TF卡分区布局陷阱
官方推荐的 dd 命令存在隐患:
sudo dd if=u-boot-sunxi-with-spl.bin of=/dev/sdb bs=1024 seek=8
更安全的方案是:
-
先擦除前1MB:
sudo dd if=/dev/zero of=/dev/sdb bs=1k count=1024 -
精确写入SPL:
sudo dd if=u-boot-sunxi-with-spl.bin of=/dev/sdb bs=512 seek=16 conv=fsync
分区表建议采用以下结构:
/dev/sdb1 - 200M FAT32 (boot)
/dev/sdb2 - 剩余空间 EXT4 (rootfs)
5.2 串口调试进阶技巧
当系统无法启动时,可以尝试:
-
在U-Boot中手动加载BL31:
load mmc 0:1 0x44000000 bl31.bin dcache flush go 0x44000000 -
检查内存映射:
md 0x44000000 0x100 # 查看BL31头部 md 0x40000000 0x100 # 检查SCP区域 -
关键地址列表:
BL31加载地址:0x44000000 SCP加载地址:0x40000000 U-Boot入口:0x4a000000
5.3 性能优化参数
在 include/configs/sunxi-common.h 中添加:
#define CONFIG_SYS_BOOTM_LEN (32 << 20) // 增加内核加载空间
#define CONFIG_SYS_MALLOC_LEN (32 << 20) // 扩大内存池
对于H618特有的设置:
#define CONFIG_SUNXI_DRAM_H618
#define CONFIG_MACH_TYPE 0x00001000
在香橙派Zero 3的调试过程中,最令我难忘的是发现BL31版本与Crust的微妙交互问题——当使用DEBUG版本的BL31时,Crust的电源管理会间歇性失效。这个教训让我明白,嵌入式开发中有时"少即是多",精简的发布版本反而能带来更稳定的表现。
更多推荐

所有评论(0)