在arch/arm/cpu/armv7/start.s重定位后接着找到函数board_init_r在重定位后的位置,然后将全局数据结构体gd_t 和重定位目标地址存分别入r0和r1中,作为函数board_init_r 的参数。跳到C函数board_init_r处执行,该函数在文件/arch/arm/lib/board.c中实现,如下:
void board_init_r (gd_t *id, ulong dest_addr)
{
char *s;
bd_t *bd;
ulong malloc_start;
gd = id; //让gd指向全局数据结构体。
bd = gd->bd;
// GD_FLG_RELOC在arch/arm/include/asm/global_data.h中定义
gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */
monitor_flash_len = _bss_start_ofs;
debug ("monitor flash len: %08lX\n", monitor_flash_len);
board_init(); /* Setup chipselects */
// board_init函数是一些关于x4412的设置,并且通过判断OmPin的值,知道开发板是何种启动方式并打印。 board_init()函数体在x4412.c中实现。
debug ("Now running in RAM - U-Boot at: %08lx\n", dest_addr);
/* The Malloc area is immediately below the monitor copy in DRAM */
malloc_start = dest_addr - TOTAL_MALLOC_LEN;
mem_malloc_init (malloc_start, TOTAL_MALLOC_LEN);
// 实现堆的分配 TOTAL_MALLOC_LEN在include/common.h中定义,值为:0x104000; dest_addr重定位地址0xc3e00000.即malloc分
//配的地址空间起始地址,其大小为0x104000。mem_malloc_init设置
//mem_malloc_start = start;
//mem_malloc_end = start + size;
//mem_malloc_brk = start; 三个参数,并将分配的堆空间初始化为0.
#if defined(CONFIG_CMD_ONENAND)
onenand_init();
#endif
#ifdef CONFIG_GENERIC_MMC
mmc_initialize(bd);
#endif
//对onenand和mmc设备初始化
/* initialize environment */
env_relocate ();
// 初始化环境变量,由于gd->env_valid等于0,所以在这里设置的是缺省环境变量。env_relocate函数是在common目录下的
//env_common.c文件中定义的。
/* IP Address */
gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
//设置IP地址。
stdio_init (); /* get the devices list going. */
//初始化各类外设,如IIC、LCD、键盘、USB等,当然只有在定义了这些外设的前提下,才对这些外设进行初始化。该函数是在common
//目录下的stdio.c文件中定义的。
jumptable_init ();
//初始化跳转表gd->jt,该跳转表是一个函数指针数组,它定义了U-Boot中基本的常用函数库。该函数是在common目录下的exports.c文
//件中定义的。
/* set up exceptions */
interrupt_init ();
/* enable exceptions */
enable_interrupts ();
//nterrupt_init函数是建立IRQ中断堆栈,enable_interrupts函数是使能IRQ中断,它们都是在arch/arm/lib目录下的interrupts.c文件中定义
//的。
/* Initialize from environment */
if ((s = getenv ("loadaddr")) != NULL) {
load_addr = simple_strtoul (s, NULL, 16);
}
//从环境变量中获取loadaddr参数,得到需要加载的地址。
#if defined(CONFIG_CMD_NET) //配置菜单CONFIG_CMD_NET=y
if ((s = getenv ("bootfile")) != NULL) {
copy_filename (BootFile, s, sizeof (BootFile));
}
#endif
//从环境变量中获取bootfile参数,得到通过TFTP加载的镜像文件名。
#ifdef BOARD_LATE_INIT
board_late_init();
#endif
#if defined(CONFIG_CMD_NET) //CONFIG_CMD_NET=y
#if defined(CONFIG_NET_MULTI)
puts ("Net: ");
#endif
eth_initialize(gd->bd);
#endif
//初始化以太网, eth_initialize函数是在net目录下的eth.c文件的第209行至第298行定义的。
/* main_loop() can return to retry autoboot, if so just run it again. */
for (;;) {
main_loop ();
}
// 死循环,调用main_loop();
/* NOTREACHED - no way out of command loop except booting */
}
void board_init_r (gd_t *id, ulong dest_addr)
{
char *s;
bd_t *bd;
ulong malloc_start;
gd = id; //让gd指向全局数据结构体。
bd = gd->bd;
// GD_FLG_RELOC在arch/arm/include/asm/global_data.h中定义
gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */
monitor_flash_len = _bss_start_ofs;
debug ("monitor flash len: %08lX\n", monitor_flash_len);
board_init(); /* Setup chipselects */
// board_init函数是一些关于x4412的设置,并且通过判断OmPin的值,知道开发板是何种启动方式并打印。 board_init()函数体在x4412.c中实现。
debug ("Now running in RAM - U-Boot at: %08lx\n", dest_addr);
/* The Malloc area is immediately below the monitor copy in DRAM */
malloc_start = dest_addr - TOTAL_MALLOC_LEN;
mem_malloc_init (malloc_start, TOTAL_MALLOC_LEN);
// 实现堆的分配 TOTAL_MALLOC_LEN在include/common.h中定义,值为:0x104000; dest_addr重定位地址0xc3e00000.即malloc分
//配的地址空间起始地址,其大小为0x104000。mem_malloc_init设置
//mem_malloc_start = start;
//mem_malloc_end = start + size;
//mem_malloc_brk = start; 三个参数,并将分配的堆空间初始化为0.
#if defined(CONFIG_CMD_ONENAND)
onenand_init();
#endif
#ifdef CONFIG_GENERIC_MMC
mmc_initialize(bd);
#endif
//对onenand和mmc设备初始化
/* initialize environment */
env_relocate ();
// 初始化环境变量,由于gd->env_valid等于0,所以在这里设置的是缺省环境变量。env_relocate函数是在common目录下的
//env_common.c文件中定义的。
/* IP Address */
gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
//设置IP地址。
stdio_init (); /* get the devices list going. */
//初始化各类外设,如IIC、LCD、键盘、USB等,当然只有在定义了这些外设的前提下,才对这些外设进行初始化。该函数是在common
//目录下的stdio.c文件中定义的。
jumptable_init ();
//初始化跳转表gd->jt,该跳转表是一个函数指针数组,它定义了U-Boot中基本的常用函数库。该函数是在common目录下的exports.c文
//件中定义的。
/* set up exceptions */
interrupt_init ();
/* enable exceptions */
enable_interrupts ();
//nterrupt_init函数是建立IRQ中断堆栈,enable_interrupts函数是使能IRQ中断,它们都是在arch/arm/lib目录下的interrupts.c文件中定义
//的。
/* Initialize from environment */
if ((s = getenv ("loadaddr")) != NULL) {
load_addr = simple_strtoul (s, NULL, 16);
}
//从环境变量中获取loadaddr参数,得到需要加载的地址。
#if defined(CONFIG_CMD_NET) //配置菜单CONFIG_CMD_NET=y
if ((s = getenv ("bootfile")) != NULL) {
copy_filename (BootFile, s, sizeof (BootFile));
}
#endif
//从环境变量中获取bootfile参数,得到通过TFTP加载的镜像文件名。
#ifdef BOARD_LATE_INIT
board_late_init();
#endif
#if defined(CONFIG_CMD_NET) //CONFIG_CMD_NET=y
#if defined(CONFIG_NET_MULTI)
puts ("Net: ");
#endif
eth_initialize(gd->bd);
#endif
//初始化以太网, eth_initialize函数是在net目录下的eth.c文件的第209行至第298行定义的。
/* main_loop() can return to retry autoboot, if so just run it again. */
for (;;) {
main_loop ();
}
// 死循环,调用main_loop();
/* NOTREACHED - no way out of command loop except booting */
}