start_amboot()函数分析

一、整体流程

   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 */
}
原文地址:https://www.cnblogs.com/amanlikethis/p/3449646.html