第一个c函数位于arch/arm/lib/board.c
start_armboot会马上申请三块空间,一块用来分配给malloc管理,一份用来存储gd_t,一份用来存储bd_t。
他们在RAM中内存布局如上图所示。
void start_armboot (void)
{
init_fnc_t **init_fnc_ptr;
char *s;
int delay = 100000;
int *p3_output_set, *p3_output_clr;
#if defined(CONFIG_VFD) || defined(CONFIG_LCD)
unsigned long addr;
#endif
/* Pointer is writable since we allocated a register for it */
gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t)); //gd指向uboot之前的地址。
/* compiler optimization barrier needed for GCC >= 3.4 */
__asm__ __volatile__("": : :"memory");
memset ((void*)gd, 0, sizeof (gd_t));
gd->bd = (bd_t*)((char*)gd - sizeof(bd_t)); //gd->bd指向gd之前。
memset (gd->bd, 0, sizeof (bd_t));
gd->flags |= GD_FLG_RELOC;
monitor_flash_len = _bss_start - _armboot_start;
/*循环调用init_sequence的初始化函数*/
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
if ((*init_fnc_ptr)() != 0) {
hang ();
}
}
/* armboot_start is defined in the board-specific linker script */
mem_malloc_init (_armboot_start - CONFIG_SYS_MALLOC_LEN,
CONFIG_SYS_MALLOC_LEN);//初始化用作malloc的内存空间。
#ifndef CONFIG_SYS_NO_FLASH //目前3250不支持nor flash.
/* configure available FLASH banks */
display_flash_config (flash_init ());
#endif /* CONFIG_SYS_NO_FLASH */
#ifdef CONFIG_VFD //3250不支持VFD
# ifndef PAGE_SIZE
# define PAGE_SIZE 4096
# endif
/*
* reserve memory for VFD display (always full pages)
*/
/* bss_end is defined in the board-specific linker script */
addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
vfd_setmem (addr);
gd->fb_base = addr;
#endif /* CONFIG_VFD */
#ifdef CONFIG_LCD //3250不支持LCD
/* board init may have inited fb_base */
if (!gd->fb_base) {
# ifndef PAGE_SIZE
# define PAGE_SIZE 4096
# endif
/*
* reserve memory for LCD display (always full pages)
*/
/* bss_end is defined in the board-specific linker script */
addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
lcd_setmem (addr);
gd->fb_base = addr;
}
#endif /* CONFIG_LCD */
#if defined(CONFIG_CMD_NAND)
puts ("NAND: ");
nand_init(); /* go init the NAND */调用driver/mtd/nand/nand.c.打印:NAND: 256 MiB
#endif
//puts("NAND init end \n");
#if defined(CONFIG_CMD_ONENAND) ////3250不支持
onenand_init();
#endif
#ifdef CONFIG_HAS_DATAFLASH ////3250不支持
AT91F_DataflashInit();
dataflash_print_info();
#endif
/* initialize environment */
env_relocate (); //祥见下面的分析
#ifdef CONFIG_VFD
/* must do this after the framebuffer is allocated */
drv_vfd_init();
#endif /* CONFIG_VFD */
#ifdef CONFIG_SERIAL_MULTI
serial_initialize();
#endif
/* IP Address */
gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr"); //获取环境变量的ip地址填充gd->bd->bi_ip_addr
stdio_init (); /* get the devices list going. */ //common/stdio.c 初始化stdio设备dev,将串口的接口注册进dev系统。
jumptable_init ();//初始化gd->jt跳转表(common/export.c)。跳转表保存的是stdio的各个函数指针
#if defined(CONFIG_API)
/* Initialize API */
api_init ();
#endif
console_init_r (); /* fully init console as a device *//(common/console.c)初始化stdin\stdout\和stderr,都指向stdio_init注册的stdio dev。gd->flags |= GD_FLG_DEVINIT;
/*输出信息:
In: serial
Out: serial
Err: serial*/
#if defined(CONFIG_ARCH_MISC_INIT)
/* miscellaneous arch dependent initialisations */
arch_misc_init ();
#endif
#if defined(CONFIG_MISC_INIT_R)
/* miscellaneous platform dependent initialisations */
misc_init_r ();
#endif
/* enable exceptions */
enable_interrupts ();
/* Perform network card initialisation if necessary */
#ifdef CONFIG_DRIVER_TI_EMAC
/* XXX: this needs to be moved to board init */
extern void davinci_eth_set_mac_addr (const u_int8_t *addr);
if (getenv ("ethaddr")) {
uchar enetaddr[6];
eth_getenv_enetaddr("ethaddr", enetaddr);
davinci_eth_set_mac_addr(enetaddr);
}
#endif
#if defined(CONFIG_DRIVER_SMC91111) || defined (CONFIG_DRIVER_LAN91C96)
/* XXX: this needs to be moved to board init */
if (getenv ("ethaddr")) {
uchar enetaddr[6];
eth_getenv_enetaddr("ethaddr", enetaddr);
smc_set_mac_addr(enetaddr);
}
#endif /* CONFIG_DRIVER_SMC91111 || CONFIG_DRIVER_LAN91C96 */
/* Initialize from environment */
if ((s = getenv ("loadaddr")) != NULL) { //3250目前不支持
load_addr = simple_strtoul (s, NULL, 16);
}
#if defined(CONFIG_CMD_NET)
if ((s = getenv ("bootfile")) != NULL) { //“uImage”内核镜像名
copy_filename (BootFile, s, sizeof (BootFile)); //复制文件
}
#endif
#ifdef BOARD_LATE_INIT
board_late_init ();
#endif
#ifdef CONFIG_GENERIC_MMC
puts ("MMC: ");
mmc_initialize (gd->bd);
#endif
#ifdef CONFIG_BITBANGMII
bb_miiphy_init();
#endif
#if defined(CONFIG_CMD_NET)
#if defined(CONFIG_NET_MULTI)
puts ("Net: ");
#endif
eth_initialize(gd->bd);
#if defined(CONFIG_RESET_PHY_R)
debug ("Reset Ethernet PHY\n");
reset_phy();
#endif
#endif
/* main_loop() can return to retry autoboot, if so just run it again. */
for (;;) {
main_loop ();
}
/* NOTREACHED - no way out of command loop except booting */
}
void hang (void)
{
puts ("### ERROR ### Please RESET the board ###\n");
for (;;);
}
1.env_relocate ()
void env_relocate (void)
{
。。。。。。。。。。
#ifdef ENV_IS_EMBEDDED
。。。。。。。。。。。。。。。。。。。
#else
/*
* We must allocate a buffer for the environment
*/
env_ptr = (env_t *)malloc (CONFIG_ENV_SIZE); //在内存的malloc区域申请一块内存存放环境变量。
DEBUGF ("%s[%d] malloced ENV at %p\n", __FUNCTION__,__LINE__,env_ptr);
#endif
if (gd->env_valid == 0) {
#if defined(CONFIG_GTH) || defined(CONFIG_ENV_IS_NOWHERE) /* Environment not changable */
puts ("Using default environment\n\n");
#else
puts ("*** Warning - bad CRC, using default environment\n\n");
show_boot_progress (-60);
#endif
set_default_env();
}
else {
env_relocate_spec (); init_sequence说到了,gd->env_valid 总为1,所以会执行这个路径。
}
gd->env_addr = (ulong)&(env_ptr->data); //初始化gd->env_addr
#ifdef CONFIG_AMIGAONEG3SEs
disable_nvram();
#endif
}
由于smartarm3250中定义了CONFIG_CMD_NAND,common/目录下的makefile会选择性的编译env_nand.c而不是其他的文件。
env_relocate_spec (); 就定义在env_nand.c。
void env_relocate_spec (void)
{
#if !defined(ENV_IS_EMBEDDED)
int ret;
ret = readenv(CONFIG_ENV_OFFSET, (u_char *) env_ptr); //CONFIG_ENV_OFFSET是在smartarm3250.h中定义的表示环境变量在flash中的偏移位置。,env_ptr是本文件内的一个全局指针。
if (ret)
return use_default();
if (crc32(0, env_ptr->data, ENV_SIZE) != env_ptr->crc)
return use_default();
#endif /* ! ENV_IS_EMBEDDED */
}
#endif /* CONFIG_ENV_OFFSET_REDUND */
#if !defined(ENV_IS_EMBEDDED)
static void use_default()
{
puts ("*** Warning - bad CRC or NAND, using default environment\n\n");
set_default_env();
}
#endif
readenv函数将从flash中读取环境变量到env_ptr。如果读取失败或者校验错误,则使用default_environment的内容填充env_ptr->data,并打印以下信息:*** Warning - bad CRC or NAND, using default environment\n\n
无论env_ptr->data指向的内容是从flash读出的,还是填充的default_environment,gd->env_addr = (ulong)&(env_ptr->data);
default_environment是根据宏生成的环境变量,从flash中读出的是用户修改过的环境变量,两者可能不一样。
总结:init_sequence之后的函数基本没有涉及到硬件初始化,大多是进行环境变量和数据结构的初始化。虽然函数很长,但是大部分都没有执行。
对与两个全局结构体的初始化过程如下表所示:
arch/arm/include/asm/global_data.h 意义 赋值顺序 第一次赋值 第二次赋值 第一次赋值函数 第二次
typedef struct global_data { uboot全局信息结构体
bd_t *bd; 指向板级信息结构体 <0> (bd_t*)((char*)gd - sizeof(bd_t)); arch/arm/lib/board.c/start_armboo
unsigned long flags; 标志变量 <0><13> |= GD_FLG_RELOC |= GD_FLG_DEVINIT arch/arm/lib/board.c/start_armboo common/console.c/console_init_r
unsigned long baudrate; 终端波特率 <5> CONFIG_BAUDRATE(115200) arch/arm/lib/board.c/init_baudrate
unsigned long have_console; 是否已经调用了serial_init() <7> 1 common/console.c/console_init_f
unsigned long env_addr; 环境变量结构体的地址 <3><10> (ulong)&default_environment[0]; (ulong)&(env_ptr->data) common/env_nand.c/env_init common/env_common.c/env_relocate
unsigned long env_valid; 环境变量的校验码是否正确 <4> 1 common/env_nand.c/env_init
unsigned long fb_base; 帧缓冲的基地址
void**jt; stdio函数的指针跳转表 <12> malloc(XF_MAX * sizeof(void *)) common/export.c/jumptable_init
} gd_t;
typedef struct bd_info { 板级配置信息结构体
int bi_baudrate; 串口终端波特率 <6> CONFIG_BAUDRATE(115200) arch/arm/lib/board.c/init_baudrate
unsigned long bi_ip_addr; ip地址 <11> getenv_IPaddr ("ipaddr") arch/arm/lib/board.c/start_armboo
struct environment_s *bi_env; 环境变量结构体的地址
ulong bi_arch_number; 板子编号 <1> MACH_TYPE_UBOOTSYS(MACH_TYPE_LPC3XXX) board/zhiyuan/smartarm3250/smart3250.c/board_init
ulong bi_boot_params; 板子启动参数 <2> CFG_ENV_ADDR(0x80000100) board/zhiyuan/smartarm3250/smart3251.c/board_init
struct { RAM描述结构体
ulong start; 开始地址 <8> PHYS_SDRAM_1;在smartarm3250.h中,起始地址 board/zhiyuan/smartarm3250/smart3250.c/dram_init
ulong size; RAM大小 <9> 0x04000000; /* 64M ,RAM大小*/ board/zhiyuan/smartarm3250/smart3250.c/dram_init
}bi_dram[CONFIG_NR_DRAM_BANKS];
} bd_t;
分析,bd的bi_env因该指向env_ptr的,可是程序中没有给它赋值,也没有使用。