u-boot源码分析 --- 启动第二阶段001

42 u-boot源码分析 --- 启动第二阶段

接着我们来看start_armboot, 从这开始应该属于bootloader的第2个阶段了,这个阶段的代码主要用c完成。

 

lib_arm/board.c:

void start_armboot (void)

{

    //该宏定义在include/asm-arm/Global_data.h

    // #define DECLARE_GLOBAL_DATA_PTR     register volatile gd_t *gd asm ("r8")

    DECLARE_GLOBAL_DATA_PTR; 

 

    ulong size;

    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 */

    //定位到RAM中的bdinfo区域中的sizeof(gd_t)处用来存放gd_t信息,详见上面的图,

    //r8中的值就是指向这个区域。

    gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));

    /* compiler optimization barrier needed for GCC >= 3.4 */

    __asm__ __volatile__("": : :"memory");

 

    memset ((void*)gd, 0, sizeof (gd_t));

    //定位到RAM中的bdinfo区域中的相关地址处用来存放bd_t信息,详见上面的图

    gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));

    memset (gd->bd, 0, sizeof (bd_t));

 

    monitor_flash_len = _bss_start - _armboot_start; //代码中RO+RW的长度

 

    //依次执行初始化函数表中的每个函数

    for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {

        if ((*init_fnc_ptr)() != 0) { 

            hang ();//执行失败就down,实际上就是一个死循环。

        }

    }

 

    /* configure available FLASH banks */

    size = flash_init ();  //flash初始化

    display_flash_config (size);  //显示flash大小

 

//如果启用CONFIG_VFD,则在RAMbss_end之后的整页处为VFD留下相应memorysmdk2410未定义

#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 */

 

//如果启用CONFIG_LCD,则在RAMbss_end之后的整页处为LCD留下相应memorysmdk2410未定义

#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 */

    //malloc功能初始化好相关信息

    mem_malloc_init (_armboot_start - CFG_MALLOC_LEN);

 

//如果开启了CFG_CMD_NAND命令后,则初始化nand.

#if (CONFIG_COMMANDS & CFG_CMD_NAND)

    puts ("NAND:");

    nand_init();       /* go init the NAND */

#endif

 

//smdk2410没定义这个宏

#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 */

//从上面初始化好的环境变量中去获取IP地址

    gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr"); 

 

//从上面初始化好的环境变量中获取MAC地址

    /* MAC Address */

    {

        int i;

        ulong reg;

        char *s, *e;

        uchar 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;

        }

    }

   

    //设备初始化

    devices_init ();   /* get the devices list going. */

    //跳转表

    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 */

    //打开中断,记得吗, 中断是在bootloader1阶段关掉的

    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) {

        load_addr = simple_strtoul (s, NULL, 16);

    }

//获取启动文件

#if (CONFIG_COMMANDS & CFG_CMD_NET)

    if ((s = getenv ("bootfile")) != NULL) {

        copy_filename (BootFile, s, sizeof (BootFile));

    }

#endif  /* CFG_CMD_NET */

 

#ifdef BOARD_LATE_INIT

    board_late_init ();

#endif

//根据命令的配置情况初始化网络

#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI)

    puts ("Net:   ");

    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 */

}

 

值得一说的是宏  DECLARE_GLOBAL_DATA_PTR

#define DECLARE_GLOBAL_DATA_PTR     register volatile gd_t *gd asm ("r8")

它定义了一个寄存器变量gd,用r8来保存gd的值。以后的函数中还会用这个宏来定义gd变量,

而此时的gd默认就是指向的是同一块内存地址(因为r8没变)

 

此时RAMbdinfo区域的存储空间如下分布:

u-boot源码分析 --- 启动第二阶段001_第1张图片

 gd_t bd_t 中存放着随后会用到的相关信息如环境变量,跳转表等。  

你可能感兴趣的:(bootl,loader)