uboot-1.1.6 /lib_arm/board.c分析

 //我们以arm为例,该文件位于lib_arm/board.c

/*
* All attempts to come up with a "common" initialization sequence
* that works for all boards and architectures failed: some of the
* requirements are just _too_ different.
* To get rid of the resulting mess of board dependent
* #ifdef'ed code we now make the whole
* initialization sequence configurable to the user.
*
* The requirements for any new initalization function is simple: it
* 新的初始化函数的要求很简单:它接收到一个指向"global"数据结构的指针,
* 作为它为其的参数,并返回一个整型码,这里0表示"继续",!0表示严重错误,系统挂起
* receives a pointer to the "global data" structure as it's only
* argument, and returns an integer return code, where 0 means
* "continue" and != 0 means "fatal error, hang the system".
*/

typedef int (init_fnc_t) (void);  //???

//这里init_sequence[]实际上是一个函数数组,每一个数组成员就是一个函数
//这里的初始化实际上是在汇编代码的基础上进一步的操作
init_fnc_t *init_sequence[] = {
    cpu_init,        /* basic cpu dependent setup 基本处理器相关配置 --cpu/arm920t/cpu.c */
    board_init,        /* basic board dependent setup 基本的板级相关配置--board/smdk2410/smdk2410.c */
    interrupt_init,        /* set up exceptions 初始化例外处理 --cpu/arm920t/s3c24x0/interrupt.c */
    env_init,        /* initialize environment 初始化环境变量 --common/env_flash.c */
    init_baudrate,        /* initialze baudrate settings 初始化波特率设置 --lib_arm/board.c */
    serial_init,        /* serial communications setup 串口通讯设置 --cpu/arm920t/s3c24x0/serial.c */
    console_init_f,        /* stage 1 init of console 控制台初始化阶段1 --common/console.c */
    display_banner,        /* say that we are here 打印uboot信息 --lib_arm/board.c */
    dram_init,        /* configure available RAM banks 配置可用的RAM --board/smdk2410/smdk2410.c */
    display_dram_config,     //显示RAM配置的大小 --lib_arm/board.c
#if defined(CONFIG_VCMA9) || defined (CONFIG_CMC_PU2)
    checkboard,
#endif
    NULL,
};

 

//start_armboot是uboot执行的第一个C语言函数,进一步完成系统初始化工作,进入主循环,处理用户输入的命令。下面是对start_armboot的简要分析

void start_armboot (void)
{
    DECLARE_GLOBAL_DATA_PTR;    /* 声明全局数据指针gd,占用r8 */

    ulong size;
    init_fnc_t **init_fnc_ptr;    /* init sequence */
    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类型指针,存储在寄存器r8中
   
    //这一行的作用就是获得指针到底从哪里开始,这里的_armboot_start指向的是_TEXT_BASE
    //这里可以参看工作日志里的那张图
    //给全局数据变量gd安排空间
    gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));    /* global data地址,栈空间分配参见start.S stack_setup部分 */
   
   
   
   
    /* compiler optimization barrier needed for GCC >= 3.4 */
   
  /* 内联汇编语句__asm__("":::"memory")向GCC声明,在此内联汇编语句出现的位置内存内容可能改变了,
    所以GCC在编译的时候,会将此因素考虑进去,而不会对代码进行优化及重新排序等操作,这样GCC会老老实实的生成汇编代码 */
     __asm__ __volatile__("": : :"memory");
  
//下面这句将会把gd所指的内存区域的(gd_t)大小的空间用"0"来填入
    memset ((void*)gd, 0, sizeof (gd_t));     //地址的清零,因为现在还没有做任何操作
 //给板子数据变量gd->bd安排空间
    gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));    /* board info 地址*/
    memset (gd->bd, 0, sizeof (bd_t));

    monitor_flash_len = _bss_start - _armboot_start;    /* .text段和.data段的总长 */  //计算uboot镜像的大小

 

//假如我们要实现很多函数的调用,并且每个函数都有独立的功能,并且我们要按一定顺序去执行它的话,那么我们可以把函数可以看做为一个数组的成员,
//这样的话,我们就可以做一个循环,按顺序调用这些函数
//这个循环的结束条件是当init_fnc_ptr为空的时候
    for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {    /* 按照initialization sequence进行初始化 */
        if ((*init_fnc_ptr)() != 0) {    /* where 0 means "continue" and != 0 means "fatal error, hang the system". */
            hang ();  //????????
        }
    }

    puts("Init flash...\n");
    /* configure available FLASH banks */
    //配置可用的flash
    size = flash_init ();    /* init nor flash */
    display_flash_config (size);

#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, defined in start.S */
    addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);    /* round up to nearest full page */
    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)
    puts ("NAND:");
    nand_init();        /* go init the 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 */
    //从环境变量中获取ip地址
    gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");

    /* MAC Address */
    //以太网接口MAC地址
    {
        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. *///设备初始化

#ifdef CONFIG_CMC_PU2
    load_sernum_ethaddr ();
#endif /* CONFIG_CMC_PU2 */

    jumptable_init ();    /* init jump table 跳转表初始化*/

    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) {
        load_addr = simple_strtoul (s, NULL, 16);    /* load address */
    }
#if (CONFIG_COMMANDS & CFG_CMD_NET)
    if ((s = getenv ("bootfile")) != NULL) {
        copy_filename (BootFile, s, sizeof (BootFile));    /* net boot file */
    }
#endif    /* CFG_CMD_NET */

#ifdef BOARD_LATE_INIT
    board_late_init ();    /* init your board */
#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. */
 //等待用户输入命令的时候,就会走到这块。
 //循环不断执行
 //主循环函数处理执行用户命令--common/main.c
 //此时,整个uboot的执行就进入等待用户输入命令,解析并执行命令的死循环中
 for (;;) {
  main_loop ();  //main_loop函数可以接收用户输入的参数然后对其进行解析,解析完之后就会去执行相应的一些命令
 }

    /* NOTREACHED - no way out of command loop except booting */
}

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值