zoukankan      html  css  js  c++  java
  • 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 */
    }
  • 相关阅读:
    Mac 安装实用开发软件和日常软件清单
    Docker zabbix-agent 监控 docker tomcat 多实例
    zabbix 组件监控概述
    实况8操作指南
    关于哲哲跳舞这件小事儿
    左耳听风笔记摘要(11-12)程序的异常处理
    左耳听风笔记摘要(07-10)推荐书单/Go/Docker
    从零开始的vue学习笔记(一)
    简述Spark工作流程
    opengl简单入门实例
  • 原文地址:https://www.cnblogs.com/amanlikethis/p/3449646.html
Copyright © 2011-2022 走看看