0K6410学习之初学Uboot_stage2

0K6410学习之初学Uboot_stage2

唉,刚刚老同学们打电话来找我月底出去聚一聚,我发誓这是我第一次这么冷静,也就是不像以前一样,不经过考虑,就一口答应下来。因为,我觉得我有很多重要的事情要做,像我这种不准备考研的学生,我必须要抓住假期的时间给自己充电,老朋友们,不好意思,请原谅我这次善意的谎言,给我在校的学习时间不多了,请接受我这次偷偷的道歉。好吧,既然已经烧好一壶水了,那就开始我的uboot stage2的学习吧!!

 

当第一阶段的汇编部分执行完,跳到stage2时,开始执行c函数start_armboot,该函数就是整个u-boot的主函数。

1、开头首先声明一个全局指针变量DECLARE_GLOBAL_DATA_PTR;这个宏定义在头文件

include/asm-arm/global_data.h 中
#define DECLARE_GLOBAL_DATA_PTR                             register volatilegd_t *gd asm ("r8")


声明一个寄存器变量 gd 占用 r8。这个宏在所有需要引用全局数据指针gd_t *gd 的源

码中都有申明,这个申明也避免编译器把r8 分配给其它的变量. 所以 gd 就是 r8,这个指针变量不另外分配内存。

2、 /* Pointer is writable since weallocated 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))强制转换类型,给指针gdgd赋一个地址,进行地址分配。都说下面是张经典的uboot映射图,确实不错啊,它把整个Uboot启动过程中的内存分配描述的相当清楚的。

monitor_flash_len = _bss_start - _armboot_start; 按照上图可以知道,这是uboot的长度。

3、接下来是一个循环,对板子的信息以及相关函数进行初始化。

for (init_fnc_ptr = init_sequence;*init_fnc_ptr; ++init_fnc_ptr) {
                   if((*init_fnc_ptr)() != 0) {
                            hang();
                   }
}


4/* 初始化堆空间 */

/* armboot_start is defined in theboard-specific linker script */
mem_malloc_init (_armboot_start -CONFIG_SYS_MALLOC_LEN,CONFIG_SYS_MALLOC_LEN);
  /*配置flash*/
 
#ifndef CONFIG_SYS_NO_FLASH
         /*configure available FLASH banks */
         display_flash_config(flash_init ());
#endif /* CONFIG_SYS_NO_FLASH */


5、接下来是一系列的初始化,不一一分析,其实是我有些函数分析不来,指针指的我头晕。。

#ifdef CONFIG_VFD
#       ifndefPAGE_SIZE
#         define PAGE_SIZE 4096
#       endif
         /*
          * reserve memory for VFD display (always fullpages)
          */
         /*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) {
#                ifndefPAGE_SIZE
#                  define PAGE_SIZE 4096
#                endif
                   /*
                    * reserve memory for LCD display (always fullpages)
                    */
                   /*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 (constu_int8_t *addr);
         if(getenv ("ethaddr")) {
                   ucharenetaddr[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")) {
                   ucharenetaddr[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 */
}


6、还有一个初始化函数,配置一些信息。

nit_fnc_t *init_sequence[] = {
#if defined(CONFIG_ARCH_CPU_INIT)
         arch_cpu_init,          /* basic arch cpu dependent setup */
#endif
         board_init,                 /* basic board dependent setup*/
#if defined(CONFIG_USE_IRQ)
         interrupt_init,           /* set up exceptions */
#endif
         timer_init,                 /* initialize timer */
#ifdef CONFIG_FSL_ESDHC
         get_clocks,
#endif
         env_init,            /* initialize environment */
         init_baudrate,          /* initialze baudrate settings */
         serial_init,                  /* serial communications setup*/
         console_init_f,          /* stage 1 init of console */
         display_banner,                 /* say that we are here */
#if defined(CONFIG_DISPLAY_CPUINFO)
         print_cpuinfo,           /* display cpu info (and speed) */
#endif
#if defined(CONFIG_DISPLAY_BOARDINFO)
         checkboard,              /* display board info */
#endif
#if defined(CONFIG_HARD_I2C) ||defined(CONFIG_SOFT_I2C)
         init_func_i2c,
#endif
         dram_init,                  /* configure available RAMbanks */
#if defined(CONFIG_CMD_PCI) || defined(CONFIG_PCI)
         arm_pci_init,
#endif
         display_dram_config,
         NULL,
};


其中display_banner是串口上打印的第一条信息的内容,自己有兴趣可以进入这个函数,修改一下,会有意想不到的结果的。

最后整个 u-boot 的执行就进入main_loop()函数等待用户输入命令,解析并执行命令的死循环中。

关于uboot stage2里面的一些重要数据结构以及一些值得注意的地方那就等下次吧,stage2的分析暂时到这里。  待续,uboot移植。。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值