2012年(9)
分类: LINUX
2012-04-19 07:52:15
现在我们再来看看 lib_arm/board.c 中的第二阶段入口函数 start_armboot :
void start_armboot (void) { init_fnc_t **init_fnc_ptr; char *s; #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)); /* 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)); memset (gd->bd, 0, sizeof (bd_t)); gd->flags |= GD_FLG_RELOC; 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 (); } } /* armboot_start is defined in the board-specific linker script */ mem_malloc_init (_armboot_start - CONFIG_SYS_MALLOC_LEN, CONFIG_SYS_MALLOC_LEN); #ifndef CONFIG_SYS_NO_FLASH /* configure available FLASH banks */ display_flash_config (flash_init ()); #endif /* CONFIG_SYS_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); vfd_setmem (addr); gd->fb_base = addr; #endif /* CONFIG_VFD */ #ifdef CONFIG_LCD /* board init may have inited fb_base */ if (!gd->fb_base) { |
gd_t 和 bd_t 这两个数据结 构比较重要,建议大家看 看。 分配一个存储全局数据的区域,地 址给指针 gd 全局数据的区清零 给 gd->bd(指针)赋值(在 gd 的 前面)并清零 gd->flags 赋值,表示已经重定向 (在内存中) monitor_flash_len 为 u-boot 代码长 度。 |
初始化循环: init_sequence 是一个初始化函数 集的函数指针数组(后面讲解) 如果有任何一个函数失败就进入死 循环。 这个始化函数集比较重要, 建议大家认真跟踪一下。 | |
初始化堆空间,清零。 | |
初始化 Nor Flash 相关参数,并显 示其大小。 | |
初始化 VFD 存储区(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); lcd_setmem (addr); gd->fb_base = addr; } #endif /* CONFIG_LCD */ #if defined(CONFIG_CMD_NAND) puts ("NAND: "); nand_init(); /* go init the NAND */ #endif #if defined(CONFIG_CMD_ONENAND) onenand_init(); #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 */ #ifdef CONFIG_SERIAL_MULTI serial_initialize(); #endif /* IP Address */ gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr"); stdio_init (); /* get the devices list going. */ jumptable_init (); #if defined(CONFIG_API) /* Initialize API */ api_init (); #endif console_init_r (); /* fully init console as a device */ #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 (); |
初始化 LCD 显存 |
初始化 Nand Flash 控制器,并显 示其容量大小。 初始化 OneNand 初始化 DataFlash 初始化环境变量,如果认为没有找 到存储其中的,就用默认值并打 印:“*** Warning - bad CRC, using default environment”。这 是我们常看到的。 | |
初始化 VFD(LCD 显示相关) | |
初始化串口。 | |
从环境变量里获取 IP 地址 初始化标准输入输出设备。比如: 串口、LCD、键盘等等 初始化全局数据表中的跳转表 gd- >jt。 跳转表是一个函数指针数组,定义 了 u-boot 中基本的常用的函数库, gd->jt 是这个函数指针数组的首指 针。 | |
初始化 API,用于为 U-boot 编写的 “应用程序” | |
初始化 console,平台无关,不一定 是串口哦,如果把标准输出设为 vga,字符会显示在 LCD 上。 | |
平台相关的其他初始化,有的平台 有 | |
#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) { load_addr = simple_strtoul (s, NULL, 16); } #if defined(CONFIG_CMD_NET) if ((s = getenv ("bootfile")) != NULL) { 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 (;;) { |
中断使能(一般不使用,很多平台 此函数是空的) |
TI 芯片中的内置 MAC 初始化(平 台相关) 一种网卡芯片初始化(平台相关) | |
获取 bootfile 参数 | |
一些板级初始化(有的板子有) | |
SD 卡/MMC 控制器初始化 | |
MII 相关初始化 网卡初始化 进入主循环,其中会读取 bootdelay 和 bootcmd 在 bootdelay 时间内按下键进入命 令行,否则执行 bootcmd 的命令。 |
main_loop ();
}
/* NOTREACHED - no way out of command loop except booting */