
清空记录
历史记录
取消
清空记录
历史记录

前言&问题场景
U‑Boot Proper的初始化分为两个阶段——board_init_f(在低地址执行的早期初始化)和board_init_r(重定位后在高地址执行的后期初始化)。
这两个阶段被重定位分隔,职责完全不同。本文通过完整时序图和每个initcall的解析,深入展示两个阶段的工作细节。
U‑Boot从低地址启动到最终停在命令行,中间经历了一个复杂的两阶段初始化过程。看到board_init_f和board_init_r这两个函数名,常常不清楚它们各自做了什么、为什么需要拆成两个阶段、以及重定位在中间扮演了什么角色。更关键的是,RK3576的重定位地址是如何通initcall序列从DRAM顶端逐步 "向下挖" 计算出来的?本文基于触觉智能Purple Pi OH2(RK3576开发板)演示,逐函数拆解initcall序列,用完整时序图还原从 DRAM 顶端“向下挖”的内存分配过程,直至U-Boot重定位完成、进入命令行。
两阶段总览
board_init_f 阶段详解
board_init_f的核心是一个initcall序列,定义在common/board_f.c。每个函数按顺序执行,主要是预留内存空间和计算重定位地址。
函数 | 职责 | 执行后 |
setup_fdt | 检查 / 准备设备树 | 设置 gd->fdt_blob |
setup_dest_addr | 计算 DRAM 大小,确定末端地址 | 设置 gd->ram_size, gd->relocaddr 初值 |
reserve_round_4k | 4KB 对齐 | gd->relocaddr 向下对齐 |
reserve_mmu | 为 MMU 页表预留空间 | gd->relocaddr 向下移动页表大小 |
reserve_video | 为显示 framebuffer 预留 | gd->relocaddr 向下移动显存大小 |
reserve_trace | 为 trace 缓冲区预留 | gd->relocaddr 向下移动 |
reserve_uboot | ★ 为 U‑Boot 自身预留空间 | gd->relocaddr 减去 monitor 长度 |
reserve_malloc | 为 malloc 堆预留 | gd->malloc_base 确定 |
reserve_board | 为板级数据预留 | board_before /board_after 钩子 |
reserve_global_data | 为 gd 结构预留 | gd->new_gd 确定 |
reserve_fdt | 为设备树预留新位置 | gd->fdt_size, fdt_reloc |
reserve_stacks | 栈空间预留 | gd->start_addr_sp |
setup_reloc | ★ 最终确定 gd->relocaddr | relocation 就绪 |
serial_init | 串口初始化 | print 信息可用 |
console_init_f | 控制台早期初始化 | 标准输出 |
DRAM末端 ┌──────────────────────────┐ ← gd->ram_top │ MMU页表 │ reserve_mmu ├──────────────────────────┤ │ Video framebuffer │ reserve_video ├──────────────────────────┤ │ Trace buffer │ reserve_trace ├──────────────────────────┤ │ U‑Boot自身 (重定位后) │ ← reserve_uboot → gd->relocaddr ├──────────────────────────┤ │ malloc堆 (CFG_MALLOC_LEN)│ reserve_malloc → gd->malloc_base ├──────────────────────────┤ │ 板级数据 (board_info) │ reserve_board ├──────────────────────────┤ │ GD (global data) │ ← reserve_global_data → gd->new_gd ├──────────────────────────┤ │ 设备树 (FDT) │ reserve_fdt ├──────────────────────────┤ │ 栈 (向下增长) │ ← reserve_stacks → gd->start_addr_sp └──────────────────────────┘
重定位:分隔符
relocate_code() 在arch/arm/lib/relocate.S(ARM 架构)中实现:
ENTRY(relocate_code) // r0 = sp (新栈地址) // r1 = new_gd (新全局数据地址) // r2 = relocaddr (目标地址) // 1. 复制自身 ldr r1, =__image_copy_start ldr r2, =__image_copy_end memcpy(r0, r1, r2 - r1) // 2. 修复.rel.dyn重定位表 ldr r2, =__rel_dyn_start ldr r3, =__rel_dyn_end fix_relocations: // 3. 跳转到新地址 ldr r0, =board_init_r // 已经过relocation fix bx r0ENDPROC(relocate_code)
board_init_r 阶段详解
重定位后,board_init_r在common/board_r.c中执行,initcall序列的核心是初始化所有设备和服务。
两阶段职责对比
维度 | board_init_f | board_init_r |
执行地址 | 低地址 (0x40200000) | 高地址 (DRAM 末端) |
核心任务 | 内存规划 + 重定位准备 | 完整设备初始化 + 命令行 |
DRAM 信息 | 使用中 | 完全就绪 |
驱动模型 | 未初始化 | 完整初始化 |
设备树 | 检查 / 预留空间 | 扫描所有节点并绑定驱动 |
环境变量 | 无 | 加载并可用 |
网络 | 无 | 完整 TCP/IP |
文件系统 | 无 | ext4/FAT 就绪 |
命令行 | 无 | 交互式 shell |
结束状态 | 调用 relocate_code | 永不返回(进入 main_loop) |
Purple Pi OH2开发板,是触觉智能RK3576核心板SOM7609系列配套的评估开发板,搭载4核A72+4核A53+M0多核异构处理器,主频2.2GHz,集成6Tops算力 NPU,轻松应对AI推理、边缘计算与轻量级AI端侧学习。配套完善SDK、丰富资料与Demo,有助于项目前期快速开发验证。
触觉智能SOM7609系列核心板尺寸仅仅40.5×40.5mm,专为空间受限场景打造。基于RK3576/RK3576J SoC,集成高性能GPU与VPU,支持4K视频编解码与多屏异显;提供PCIe、USB3.2、双路千兆以太网、MIPI-DSI/CSI、eDP、CAN、SPI、I2C等丰富接口,灵活扩展。支持Linux、Android、开源鸿蒙OpenHarmony等丰富系统,配套硬件设计指南、源码与技术支持,助力产品快速落地。
