一、前言
u-boot第一阶段的代码最终跳转到这里运行
这个函数做了两件事:
1、将u-boot整个的代码拷贝到内存当中
2、将pc指针指向SDRAM中的u-boot起始代码
二、u-boot第二阶段代码(一)
(大家接下来看到的代码是只与exynos4412的u-boot相关的代码,本人对代码做了精简,方便理清启动流程)
arch/arm/lib/crt0.S
_main:
/*
* Set up initial C runtime environment and call board_init_f(0).
*/
/*
1) Start . S 文件执行到bl main函数时,就会跳到crt0.s这个文件中。
2) 调用board_init_f函数与设置C语言运行环境
3) (CONFIG_SYS_INIT_SP_ADDR = 0X43E00000- 128)
4) 把这个地址作为sp数据栈指针
5) 这种操作是将sp栈指针所指地址8字节对齐
6) GD_SIZE = 128 将sp指针又向下偏移128字节后对齐
7) 将此时sp指针的值保存在r8寄存器中,将0写入r0寄存器中传参到 board_init_f函数
注意这个地方的
blboard_init_f
函数它会朝两个方向跳转执行
:
一是
U_boot
第一阶段的程序
:
将整个
bootloader
拷贝到内存当中的程序。。。。二是
U_boot
第二阶段的
:
执行初始化列表,为
U_boot
重定向预留内存 */
ldr
sp, =(CONFIG_SYS_INIT_SP_ADDR)
bic
sp, sp, #7
/* 8-byte alignment for ABI compliance */
sub
sp, #GD_SIZE
/* allocate one GD above SP */
bic
sp, sp, #7
/* 8-byte alignment for ABI compliance */
mov
r8, sp
/* GD is above SP */
mov
r0, #0
bl
board_init_f
arch/arm/lib/board.c
typedef struct bd_info {
unsigned int
bi_baudrate;
/* serial console baudrate */
ulong
bi_arch_number;
/* unique id for this board */
ulong
bi_boot_params;
/* where this board expects params */
unsigned long
bi_arm_freq; /* arm frequency */
unsigned long
bi_dsp_freq; /* dsp core frequency */
unsigned long
bi_ddr_freq; /* ddr frequency */
struct
/* RAM configuration */
{
ulong start;
ulong size;
}
bi_dram[CONFIG_NR_DRAM_BANKS];
} bd_t;
/*为 int () ( void ) 这种函数类型取个别名为init_fnc_t*/
typedef int (init_fnc_t) (void);
/*gd.mon_len= _bss_end_ofs;(u_boot大小)*/
gd{
.mon_len = _bss_end_ofs;(u_boot大小)
}
/* int () ( void )
init_sequence[] 数组中存放的是init_fnc_t这种类型的函数入口地址*/
init_fnc_t *init_sequence[] = {
/*获取cpu id*/
arch_cpu_init,
/* basic arch cpu dependent setup */
/*定时器初始化*/
timer_init,
/* initialize timer */
/*环境变量初始化:指定了一个默认的环境变量
env_init 最最开始没有设置板子的环境变量setenv ,就有这个默认的环境变量,如果设置了环境变量,就从emmc读取 env(setenv后save保存的)*/
env_init,
/* initialize environment */
/*初始化波特率*/
init_baudrate,
/* initialze baudrate settings */
/*初始化串口:确定哪一个串口设备输出(默认的输出是哪一个串口) 宏定义开关发现是2号串口*/
serial_init,
/* serial communications setup */
/*控制台一级初始化*/
console_init_f,
/* stage 1 init of console */
/*打印u_boot版本信息*/
display_banner,
/* say that we are here */
/*打印cpu的信息*/
print_cpuinfo,
/* display cpu info (and speed) */
/*记录内存的大小
内存大小: gd->ram_size= 4x256M */
dram_init,
/* configure available RAM banks */
NULL,
};
/*定义一个bd_t结构体类型的指针
init_fnc_ptr指向一块地址该地址装的也是一个地址,此地址指向init_fnc_t类型的一个函数
定义一个gd_t结构体类型的指针Unsigned long 类型*/
void board_init_f(ulong bootflag)
{
bd_t *bd;
init_fnc_t **init_fnc_ptr;
gd_t *id;
ulong addr, addr_sp;
void *new_fdt = NULL;
size_t fdt_size = 0;
//#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8")
/*以内联汇编的形式定义了一个定义一个gd_t结构体类型的指针
指向r8 所指向的地址(CONFIG_SYS_INIT_SP_ADDR =0X43E00000 - 128)把这个地址作为sp数据栈指针*/
//DECLARE_GLOBAL_DATA_PTR;
memset((void *)gd, 0, sizeof(gd_t));
//记录uboot大小
gd->mon_len = _bss_end_ofs;
//调用初始化序列中的每一个函数
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
if ((*init_fnc_ptr)() != 0) {
hang ();
}
}
下一节将会分析u-boot重定向时在内存中到底是怎么划分的
未完待续。。。。。。
(本人技术经验浅薄,文中难免有疏漏错误之处,请在评论中予以提醒,共同进步,非常感谢!)