Skip to main content

为 T527 准备 TF-A

芯片丝印写着 T527,TF-A 的平台目录却叫 sun55i_a523。这不是选错了芯片,而是移植时经常遇到的第一类问题:硬件型号、SoC 家族名和源码目录名并不总是一一对应。

这一篇先用 Linux 设备树和 TF-A 平台文件确认这层关系,再检查官方 TF-A 是否包含对应平台,最后引入公开的开发提交生成 bl31.bin。后面 U-Boot FIT 中使用的 BL31,服务的仍然是 Avaota A1 上的 T527。

Linux 的 Avaota A1 板级设备树给出了最直接的对应关系:

arch/arm64/boot/dts/allwinner/sun55i-t527-avaota-a1.dts
#include "sun55i-a523.dtsi"

/ {
model = "Avaota A1";
compatible = "yuzukihd,avaota-a1", "allwinner,sun55i-t527";
};

compatible 标识板上的 SoC 是 T527,包含的 sun55i-a523.dtsi 则提供 CPU、GIC、时钟、电源控制器和外设寄存器等公共描述。TF-A 沿用同样的平台命名,只提供 plat/allwinner/sun55i_a523/,所以构建 T527 所需的 BL31 时使用 PLAT=sun55i_a523

层次本课程使用的名称表示什么
实物芯片T527Avaota A1 上焊接的 SoC
Linux 板级目标sun55i-t527-avaota-a1.dtsAvaota A1 的板级连接与设备配置
Linux 公共描述sun55i-a523.dtsiT527 复用的 sun55i SoC 公共硬件描述
TF-A 平台目标PLAT=sun55i_a523BL31 使用的 EL3、PSCI 和电源管理实现

因此,这一步不是移植一块 A523 开发板,也不是把 A523 固件直接烧到 T527。实际工作是把 T527 可复用的 sun55i_a523 平台代码加入 TF-A,并通过 Avaota A1 的启动、多核和复位结果验证复用是否成立。

在 AArch64 启动链中,SPL 不能直接把普通 U-Boot 当成最高异常级固件运行。SPL 先加载 BL31,BL31 在 EL3 建立安全监控环境,再把 U-Boot proper 作为非安全世界的 BL33 启动。Linux 以后发起的 CPU 上电、关机和系统复位请求,也会通过 PSCI 回到 BL31。因此,能够打印 U-Boot 版本并不能证明 TF-A 已经适配完整;多核启动和复位仍是同一份平台代码的后续验证。

检查官方版本的平台支持

TF-A 2.15.0 的 plat/allwinner/ 中既没有 sun55i_t527,也没有 T527 可以复用的 sun55i_a523 平台目录,直接执行 make PLAT=sun55i_a523 会因找不到平台而停止。课程使用的提交来自公开开发历史,不能把它表述成“TF-A 2.15.0 已经原生支持 T527”。

进入 mainline-a1,单独建立用于保存该开发提交的源码目录:

git clone --no-checkout \
https://github.com/ARM-software/arm-trusted-firmware.git \
trusted-firmware-a-a523

git -C trusted-firmware-a-a523 fetch --depth 1 origin \
b5de74a685fb73b784e45bbbd18dd9a0c528d8b2
git -C trusted-firmware-a-a523 checkout --detach FETCH_HEAD
git -C trusted-firmware-a-a523 rev-parse HEAD

最后一条命令应输出完整提交号 b5de74a685fb73b784e45bbbd18dd9a0c528d8b2。该提交可在 TF-A 官方 GitHub 镜像 中查看。

T527 复用的 TF-A 平台代码

find trusted-firmware-a-a523/plat/allwinner/sun55i_a523 \
-maxdepth 2 -type f | sort

关键文件组成如下:

plat/allwinner/sun55i_a523/
├── include/
│ ├── sunxi_ccu.h 时钟控制寄存器
│ ├── sunxi_cpucfg.h CPU 与热插拔寄存器
│ ├── sunxi_mmap.h SRAM、DRAM 和外设地址
│ └── sunxi_spc.h 安全外设控制器
├── platform.mk 架构、CPU 数量和公共代码选择
├── sunxi_idle_states.c PSCI 空闲状态
└── sunxi_power.c CPU 上下电入口

platform.mk 中最先需要核对的是架构和 CPU 拓扑:

ARM_ARCH_MAJOR := 8
ARM_ARCH_MINOR := 2
PLATFORM_MAX_CPUS_PER_CLUSTER := 8
STANDALONE_WATCHDOG := 1

这些值与 T527 的八核 Cortex-A55 结构对应,让 TF-A 选择 Armv8.2、GICv3 和八核拓扑。sunxi_mmap.h 还给出两处会进入 FIT 的地址关系:DRAM 从 0x40000000 开始,BL31 位于 SRAM A2 的 0x54000。这里核对的是 T527 是否能够复用这些平台事实,不能因为目录名包含 A523 就跳过硬件和启动验证。

图中的三个输入分别解决处理器特性、链接地址和多核电源管理;缺少任意一层都不能只靠一个 PLAT 名称补齐。

0x54000 怎样进入后续启动链

sunxi_mmap.h 把这个 sun55i 平台的 BL31 区域定义在 SRAM A2。平台基址 0x40000 加上 BL31 偏移 0x14000,得到运行地址 0x54000。这个值同时约束两个独立产物:TF-A 链接器必须把 BL31 链接到该地址,U-Boot 的 firmware FIT 也必须把 atf 节点加载到该地址。

TF-A 平台内存图 ──决定──> BL31 ELF 入口/链接地址

└──必须等于── FIT 中 atf 的 load 地址

如果两者不一致,SPL 仍可能把文件读入内存并打印 FIT 节点,但跳转后会立即异常,因为 BL31 中的绝对地址和实际存放位置不同。后续查看 FIT 时,要把 dumpimage 显示的 0x54000 与这里的内存图交叉检查,而不是把它当作一个可任意选择的加载地址。

原生 PSCI 与 SCPI 的差别

SUNXI_PSCI_USE_NATIVE=1 让 BL31 直接使用 sunxi_power.c 和当前平台的 CPU 配置寄存器完成核心上下电。SCPI 路径则把请求交给另一个系统控制处理器;只有板上存在相应固件和通信通道时才能选择。Avaota A1 当前启动组合没有加入独立 SCP 固件,因此这里显式关闭 SCPI,而不是因为两种接口可以随意互换。

编译 T527 使用的 bl31.bin

仍在 mainline-a1 目录,设置 Tina5 SDK 中的交叉工具链:

sdk_dir=$(cd ../.. && pwd)
cross="${sdk_dir}/out/toolchain/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-"
"${cross}gcc" --version

确认编译器可执行后构建调试版本:

make -C trusted-firmware-a-a523 \
CROSS_COMPILE="$cross" PLAT=sun55i_a523 DEBUG=1 \
SUNXI_PSCI_USE_SCPI=0 SUNXI_PSCI_USE_NATIVE=1 clean

make -C trusted-firmware-a-a523 -j"$(nproc)" \
CROSS_COMPILE="$cross" PLAT=sun55i_a523 DEBUG=1 \
SUNXI_PSCI_USE_SCPI=0 SUNXI_PSCI_USE_NATIVE=1 bl31

构建参数必须与前面的平台选择一致。PLAT=sun55i_a523 选择平台目录,DEBUG=1 保留早期日志和断言,两个 PSCI 参数选择电源管理实现。检查产物:

bl31=trusted-firmware-a-a523/build/sun55i_a523/debug/bl31.bin
test -s "$bl31"
stat -c '%n %s bytes' "$bl31"
"${cross}readelf" -h \
trusted-firmware-a-a523/build/sun55i_a523/debug/bl31/bl31.elf \
| grep -E 'Class:|Machine:|Entry point'

文件非空且 ELF 显示 AArch64 后,再记录 Entry point address。它应与当前平台链接布局相符,随后才能把 bl31.bin 交给 U-Boot。换用其他开发提交时,要重新检查平台目录、链接地址和 PSCI 实现,不能只替换提交号后沿用先前生成的 FIT。

编译成功只证明平台代码能够生成固件;CPU 热插拔和系统复位仍要在 Linux 启动后通过 PSCI 实测。若单核可以启动而其他 CPU 一直离线,第一检查对象是 sunxi_power.c、CPU 拓扑和 PSCI 日志,而不是 Linux 的 Buildroot 配置。

继续:组合 U-Boot FIT