============================================
作者:yuanlulu
http://blog.csdn.net/yuanlulu
版权没有,但是转载请保留此段声明
============================================
第一个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 (;;);
}
2.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的,可是程序中没有给它赋值,也没有使用。