u_boot_2013.01启动流程分析(二)(for exynos4412)
一、前言
u-boot第一阶段的代码最终跳转到这里运行
这个函数做了两件事:
1、将u-boot整个的代码拷贝到内存当中
2、将pc指针指向SDRAM中的u-boot起始代码
二、u-boot第二阶段代码(一)
_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函数
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
/*定义了bd-t 的结构体类型*/
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*/
/*gd.mon_len= _bss_end_ofs;(u_boot大小)*/
.mon_len = _bss_end_ofs;(u_boot大小)
}
/* int () ( void )
init_sequence[] 数组中存放的是init_fnc_t这种类型的函数入口地址*/
/*获取cpu id*/
arch_cpu_init, /* basic arch cpu dependent setup */
/*定时器初始化*/
timer_init, /* initialize timer */
/*环境变量初始化:指定了一个默认的环境变量
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 */
NULL,
};
/*定义一个bd_t结构体类型的指针
init_fnc_ptr指向一块地址该地址装的也是一个地址,此地址指向init_fnc_t类型的一个函数
定义一个gd_t结构体类型的指针Unsigned long 类型*/
{
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数据栈指针*/
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重定向时在内存中到底是怎么划分的