您的位置:首页 > 运维架构

U-boot源码简要分析(二)

2010-12-06 16:24 211 查看
现在我们再来看看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 av
4000
ailable 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) {
#            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 ();
#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 (;;) {
              main_loop ();
       }
 
       /* NOTREACHED - no way out of command loop except booting */
}
 
 
 
 
 
 
 
 
 
gd_t bd_t这两个数据结构比较重要,建议大家看看。
分配一个存储全局数据的区域,地址给指针 gd
 
 
全局数据的区清零
给 gd->bd(指针)赋值(在gd的前面)并清零
 
gd->flags 赋值,表示已经重定向(在内存中)

monitor_flash_len为u-boot代码长度。

初始化循环
init_sequence 是一个初始化函数集的函数指针数组(后面讲解)
如果有任何一个函数失败就进入死循环。

这个始化函数集比较重要,建议大家认真跟踪一下。

 
 
初始化堆空间,清零。

 

 
初始化Nor Flash相关参数,并显示其大小。

 
 
 
 
 

初始化VFD存储区(LCD显示相关)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
初始化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上。

 
 
平台相关的其他初始化,有的平台有
 
 
 
 

 

 
 
中断使能(一般不使用,很多平台此函数是空的)

 
 

 
 
 
TI芯片中的内置MAC初始化(平台相关)
 
 
 
 
 
 
 
 
 
 
一种网卡芯片初始化(平台相关)
 
 
 
 
 
 
 
 
 
  
 

 

 
 
获取 bootfile参数
 
 

 

 
 
一些板级初始化(有的板子有)
 

 

  
SD/MMC控制器初始化
 

 

 
 
MII相关初始化
 
  
 
网卡初始化
 
 
 
 
 
 
 
进入主循环,其中会读取bootdelay和bootcmd
在bootdelay时间内按下键进入命令行,否则执行bootcmd的命令。
标有红色的是比较重要的地方。
大致的U-boot启动流程就简单介绍到这。

                                                                       回目录 u-boot移植详细文档
原文出处:http://blog.chinaunix.net/u1/34474/showart.php?id=2217086
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息