一、整体流程
start_amboot()函数是执行完start.S汇编文件后第一个C语言函数,完成的功能自然还是初始化的工作 。
1、全局变量指针r8设定,以及全局变量区清零
2、执行一些类初始化函数,详细见init_sequence所对应的函数
3、初始化norflash
4、初始化显示器
5、初始化堆区
6、初始化nandflash
7、环境变量重定位,详见uboot环境变量(env)初始化
8、网络设置
9、设备初始化,详见uboot的devices_init函数分析
10、函数跳转表初始化,详见uboot的jumptable_init函数分析
11、控制台初始化
12、中断使能
最终:进入main_loop
二、函数注释
void start_armboot (void) { init_fnc_t **init_fnc_ptr; char *s; #ifndef CFG_NO_FLASH ulong size; #endif #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 - CFG_MALLOC_LEN - sizeof(gd_t)); //给全局变量指针gd赋值 /* compiler optimization barrier needed for GCC >= 3.4 */ __asm__ __volatile__("": : :"memory"); //实验中这句话没什么作用 memset ((void*)gd, 0, sizeof (gd_t)); //gd_t存储区域清零 gd->bd = (bd_t*)((char*)gd - sizeof(bd_t)); memset (gd->bd, 0, sizeof (bd_t)); monitor_flash_len = _bss_start - _armboot_start; for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {//执行一系列初始化函数 if ((*init_fnc_ptr)() != 0) { hang (); } } #ifndef CFG_NO_FLASH /* configure available FLASH banks */ size = flash_init (); //norflash的初始化 display_flash_config (size); //打印norflash的大小 #endif /* CFG_NO_FLASH */ #ifdef CONFIG_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); size = vfd_setmem (addr); gd->fb_base = addr; #endif /* CONFIG_VFD */ #ifdef CONFIG_LCD # 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); size = lcd_setmem (addr); gd->fb_base = addr; #endif /* CONFIG_LCD */ /* armboot_start is defined in the board-specific linker script */ mem_malloc_init (_armboot_start - CFG_MALLOC_LEN); #if (CONFIG_COMMANDS & CFG_CMD_NAND) //如果定义了CFG_CMD_NAND,就 puts ("NAND: ");//打印nand信息 nand_init(); //进行nand 初始化 #endif #ifdef CONFIG_HAS_DATAFLASH 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 */ /* IP Address */ gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr"); //从环境变量获取网卡的MAC地址并填充gd结构体变量 /* MAC Address */ { int i; ulong reg; char *s, *e; char tmp[64]; i = getenv_r ("ethaddr", tmp, sizeof (tmp)); s = (i > 0) ? tmp : NULL; for (reg = 0; reg < 6; ++reg) { gd->bd->bi_enetaddr[reg] = s ? simple_strtoul (s, &e, 16) : 0; if (s) s = (*e) ? e + 1 : e; } #ifdef CONFIG_HAS_ETH1 i = getenv_r ("eth1addr", tmp, sizeof (tmp)); s = (i > 0) ? tmp : NULL; for (reg = 0; reg < 6; ++reg) { gd->bd->bi_enet1addr[reg] = s ? simple_strtoul (s, &e, 16) : 0; if (s) s = (*e) ? e + 1 : e; } #endif } devices_init ();//设备初始化 /* get the devices list going. */ #ifdef CONFIG_CMC_PU2 load_sernum_ethaddr (); #endif /* CONFIG_CMC_PU2 */ jumptable_init (); //跳转表初始化,跳转表建立在堆区 console_init_r (); //控制端初始化 /* fully init console as a device */ #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_CS8900 cs8900_get_enetaddr (gd->bd->bi_enetaddr); //获得网卡地址 #endif #if defined(CONFIG_DRIVER_SMC91111) || defined (CONFIG_DRIVER_LAN91C96) if (getenv ("ethaddr")) { smc_set_mac_addr(gd->bd->bi_enetaddr); } #endif /* CONFIG_DRIVER_SMC91111 || CONFIG_DRIVER_LAN91C96 */ /* Initialize from environment */ if ((s = getenv ("loadaddr")) != NULL) {//读取环境变量loadaddr到全局变量load_addr中 load_addr = simple_strtoul (s, NULL, 16); } #if (CONFIG_COMMANDS & CFG_CMD_NET) if ((s = getenv ("bootfile")) != NULL) {//读取环境变量bootfile到全局变量BootFile中
copy_filename (BootFile, s, sizeof (BootFile)); } #endif /* CFG_CMD_NET */ #ifdef BOARD_LATE_INIT //没有定义 board_late_init (); #endif #if (CONFIG_COMMANDS & CFG_CMD_NET) #if defined(CONFIG_NET_MULTI) puts ("Net: "); #endif eth_initialize(gd->bd); #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 */ }