启动 U-Boot 并加载 Linux
SPL 把 FIT 装入 DRAM 后,BL31 会把 U-Boot proper 作为 BL33 启动。此时启动链已经离开片内 SRAM,但还没有进入 Linux:U-Boot 要先建立自己的运行环境,再从 FAT 分区读取 extlinux.conf、Linux Image 和板级 DTB。
U-Boot proper 要同时满足两个彼此独立的条件:自身能够在安全的 DRAM 地址运行,并且能够从 eMMC 完整读取约 49 MiB 的 Image。前者由内存布局决定,后者由 MMC 请求大小和控制器状态决定。
确认 TF-A 已进入 U-Boot
当前实机日志连续出现:
NOTICE: BL31: v2.12.0(debug):b5de74a68
NOTICE: BL31: Built : 10:07:57, Aug 22 2026
U-Boot 2026.07-dirty (Sep 01 2026 - 23:27:38 -0400)
CPU: Allwinner A523 (SUN55I)
Model: Avaota A1
U-Boot 输出 A523 (SUN55I) 是源码平台族名称,Model: Avaota A1 来自板级设备树;板上的实际芯片仍是 T527。版本字符串出现说明 BL31 已经跳到 U-Boot 入口,但只有继续出现设备初始化和启动扫描,才能证明 U-Boot 的运行环境稳定。
限制 U-Boot 的内存使用范围
Avaota A1 配有 4 GiB DRAM,地址范围跨过 4 GiB 边界。U-Boot 默认从可用内存顶端向下选择重定位位置,而当前工程把 U-Boot 自身的运行与分配范围限制在低地址,避免早期内存管理访问尚未稳定验证的高地址区域。
当前工程在 arch/arm/mach-sunxi/board.c 中把 U-Boot 自身可使用的顶端 限制到 0x50000000:
if (IS_ENABLED(CONFIG_MACH_SUN55I_A523) &&
gd->ram_top > 0x50000000ULL) {
printf("LYNX_RAM_TOP_SAFE: detected_top=0x%llx "
"usable_top=0x50000000\n",
(unsigned long long)gd->ram_top);
return 0x50000000ULL;
}
实机输出为:
DRAM: LYNX_RAM_TOP_SAFE: detected_top=0x140000000 usable_top=0x50000000
4 GiB
0x140000000 正好是 0x40000000 起始地址加 4 GiB 容量。返回 0x50000000 只限制 U-Boot 的早期分配位置,没有把 Linux 可见内存缩成 256 MiB;进入 Linux 后,free -h 仍显示约 3.8 GiB 内存。
当前 avaota-a1_defconfig 还启用了:
CONFIG_EXPERT=y
CONFIG_SKIP_RELOCATE=y
CONFIG_SKIP_RELOCATE=y 使 U-Boot 继续在 FIT 指定的低地址运行,并与前面的内存上限共同组成当前工程的启动方案。若要关闭该选项或恢复高地址重定位,应重新检查 bdinfo、异常寄存器和冷启动日志,不能只删除配置项。
为什么 25 MHz 仍会读 Linux 超时
当 U-Boot 能找到 extlinux、却无法完整加载 Image 时,串口通常停在:
Found /extlinux/extlinux.conf
Retrieving file: /Image
LYNX_MMC_HW_DIAG: mmc=2 cmd=18 arg=0x00008208 err=-110
blocks=65535 blocksize=512 width=8 clock=25000000
Error reading cluster
Skipping mainline for failure retrieving kernel
这一行已经给出关键线索:单次 CMD18 请求包含 65,535 个块,即接近 32 MiB。控制器的数据完成等待有固定超时;降低时钟虽然改善采样稳定性,却让同样大小的请求耗时更长,因此“大请求 + 低速率”仍会超时。
当前工程同时限制 SPL 旧式 MMC 路径和 U-Boot proper 驱动模型路径:
cfg->f_max = 25000000;
cfg->b_max = 128;
128 个 512 字节块等于 64 KiB。U-Boot 的块层会把读取 Image 的大请求拆成许多 64 KiB 小请求,每个请求都能在控制器超时前结束。
drivers/mmc/mmc.c 还为这个受限路径增加了一次重试:第一次读取失败后,sunxi 驱动先复位控制器,然后块层只重试同一小段一次。重试用于吸收偶发恢复,不会无限循环,也不应掩盖持续性的 CRC、供电或介质故障。
区分三个阶段的 MMC 编号
同一颗 eMMC 在不同阶段出现了不同编号:
| 日志所在阶段 | 当前实机名称 | 含义 |
|---|---|---|
| SPL/sunxi 驱动 | MMC2、mmc=2 | T527 的硬件控制器编号 |
| U-Boot 文件扫描 | mmc 1:1 | U-Boot 枚举后的第 1 个 MMC 设备、第 1 个分区 |
| 主线 Linux | /dev/mmcblk1p2 | Linux 本次 probe 顺序得到的块设备名 |
| FES 烧录阶段 | eMMC User Area / Boot0 | OpenixCLI 使用的物理存储区域 |
这些编号没有跨阶段稳定的对应关系。编写 Linux 启动参数和检查脚本时,应通过卷标、设备属性或当前日志确认目标,不能把 OpenixCLI 的物理存储区域名称当作 Linux 块设备编号。
确认 extlinux 自动启动 Linux
修改后的实机日志表明,大文件读取已经走通:
LYNX_MMC_SAFE_IO_DM: mmc=2 f_max=25000000 b_max=128 force_width=4
Scanning mmc 1:1...
Found /extlinux/extlinux.conf
Retrieving file: /Image
Retrieving file: /sun55i-t527-avaota-a1.dtb
Moving Image from 0x40080000 to 0x40200000, end=43310000
Starting kernel ...
这里的完成条件不是出现 =>。=> 只是 U-Boot 命令提示符,通常表示自动启动被按键打断、启动脚本结束或启动项失败。真正证明默认路径已进入 Linux 的是 Starting kernel ...。
工程还把启动倒计时设为 5 秒并清空 PREBOOT,避免 USB 键盘和网络预启动逻辑反复干扰串口调试:
CONFIG_BOOTDELAY=5
CONFIG_PREBOOT=""
# CONFIG_USB_KEYBOARD is not set
此外,board_boot_order() 为 A523/T527 增加了失败后返回 FEL 的第二启动项。当 eMMC 冷启动再次失败时,板卡仍有机会回到 BootROM FEL,便于重新烧录。它是恢复通道,不是 eMMC 成功启动所依赖的正常步骤。