我试图通过浏览源代码来了解BeagleBone Black的启动过程。假设Iam将MLO和u-boot.img文件保存在micro-SD卡中,并使BeagleBone从SD卡启动。
根据我的理解,首先执行ROM代码,并将MMC文件从MMC加载到SOC的内部SRAM中。 MLO文件包含x-loader的代码,即第二阶段程序加载器(SPL)。然后,SPL设置DRAM并将第三级程序加载器(U-boot适当)复制到DRAM中。 U-boot适当直接从DRAM开始执行。
U-boot本身的体系结构相关部分位于U-boot源的arch / arm /目录中。 与SPL相关的代码位于spl /目录中。(执行make mrproper后跟make SPL,* .o文件只在spl /目录中创建)
对于U-boot,我猜测这是执行流程 - arch / arm / cpu / armv7 / start.S位于复位向量(因此它首先运行),并在初始化后调用' _main'程序位于arch / arm / lib / crt0.S。
在crt0.S中,调用board_init_f(),它设置DRAM(和其他东西),然后返回到它停止的位置(在main_中)。它稍后调用函数relocate_code,它再次将它重新定位到DRAM。
ENTRY(_main)
/*
* Set up initial C runtime environment and call board_init_f(0).
*/
#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
ldr r0, =(CONFIG_SPL_STACK)
#else
ldr r0, =(CONFIG_SYS_INIT_SP_ADDR)
#endif
bic r0, r0, #7 /* 8-byte alignment for ABI compliance */
mov sp, r0
bl board_init_f_alloc_reserve
mov sp, r0
/* set up gd here, outside any C code */
mov r9, r0
bl board_init_f_init_reserve
mov r0, #0
bl board_init_f
#if ! defined(CONFIG_SPL_BUILD)
/*
* Set up intermediate environment (new sp and gd) and call
* relocate_code(addr_moni). Trick here is that we'll return
* 'here' but relocated.
*/
ldr r0, [r9, #GD_START_ADDR_SP] /* sp = gd->start_addr_sp */
bic r0, r0, #7 /* 8-byte alignment for ABI compliance */
mov sp, r0
ldr r9, [r9, #GD_BD] /* r9 = gd->bd */
sub r9, r9, #GD_SIZE /* new GD is below bd */
adr lr, here
ldr r0, [r9, #GD_RELOC_OFF] /* r0 = gd->reloc_off */
add lr, lr, r0
#if defined(CONFIG_CPU_V7M)
orr lr, #1 /* As required by Thumb-only */
#endif
ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */
b relocate_code
here:
为什么U-boot需要再次设置DRAM并重新定位自己,如果这已经由SPL完成了?我在这里错过了什么吗?
答案 0 :(得分:0)
为什么U-boot需要再次设置DRAM并重新定位自己,如果这已经由SPL完成了?
重新定位到内存顶部是为了最大化连续的可用空间
您可以在此高内存地址上构建/链接并加载U-Boot(以保存在副本上)。但是,无论何时使用添加的功能重建U-Boot并且图像变大,都必须重新计算该加载地址。
这也意味着必须改变SPL。
BTW “设置DRAM”通常会被认为是初始化DRAM控制器,这在此阶段尚未完成。
除了重定位代码之外,U-Boot还必须移动堆栈和堆,即C运行时环境。
我在这里错过了什么吗?
在主内存中加载U-Boot更方便,然后让U-Boot将自身重定位到高内存。