Chinaunix首页 | 论坛 | 博客
  • 博客访问: 32945
  • 博文数量: 16
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 10
  • 用 户 组: 普通用户
  • 注册时间: 2014-11-03 11:02
文章分类
文章存档

2014年(16)

我的朋友

分类: 嵌入式

2014-11-27 15:18:51

原文地址:uboot浅析 - start_armboot 作者:changyongID

下面的start_armboot中,去掉一些被预编译包含的代码。如我的板子上没有LCD、VFD、NOR FLASH等,
所以在分析时就直接将它们略过了。

   314 /* Pointer is writable since we allocated a register for it */
   315 gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));
   316 /* compiler optimization barrier needed for GCC >= 3.4 */
   317 __asm__ __volatile__("": : :"memory");
   318
   319 memset ((void*)gd, 0, sizeof (gd_t));
   320 gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));
   321 memset (gd->bd, 0, sizeof (bd_t));
   322
   323 monitor_flash_len = _bss_start - _armboot_start;


关于gd_t和bd_t结构体,见
http://blog.chinaunix.net/u3/93566/showart_2097710.html

_armboot_start 定义代码段的起始地址,定义在start.S中

_armboot_start:
    .word _start

可见其中保存的是第一条指令_start的地址。编译的时候指定了TEXT_BASE为0x33f80000,所以
_armboot_start中的值也为0x33f80000。

CONFIG_SYS_MALLOC_LEN -> include/configs/smdk2410.h

#define CONFIG_SYS_MALLOC_LEN  (CONFIG_ENV_SIZE + 128*1024)
#define CONFIG_ENV_SIZE        0x10000    /* Total Size of Environment Sector */

=> CONFIG_SYS_MALLOC_LEN = 0x10000 + 128 * 1024 = 0x10000 + 0x20000 = 0x30000
    即 192k

sizeof(gd_t) = 9 * 4 = 36 = 0x24 (这里没有VDF和LCD)

上面这些代码就是定义gd 和 bd的位置,并将这两个结构体先清零,大致的布局如下

+---------+ -> 0x34000000 _armboot_start
|  512k   |
+---------+ -> 0x33f80000
| 192k    |    CONFIG_SYS_MALLOC_LEN = CONFIG_ENV_SIZE(0x1000) + 128*1024 = 0x30000
+---------+ -> 0x33f50000
|         |    sizeof(gd_t) = 0x24 uboot配置信息
+---------+ -> gd
|         |    sizeof(bd_t)  板级相关信息
+---------+ -> bd
|         |
+---------+

上面317行  __asm__ __volatile__("": : :"memory"); 是内嵌汇编的知识

* __asm__用于指示编译器在此插入汇编语句
__volatile__用于告诉编译器,严禁将此处的汇编语句与其它的语句重组合优化。即:原原本本按原来的样子处理这这里的汇编。
* memory强制gcc编译器假设RAM所有内存单元均被汇编指令修改,这样cpu中的registers和cache中已缓存的内存单元中的数据将作 废。cpu将不得不在需要的时候重新读取内存中的数据。这就阻止了cpu又将registers,cache中的数据用于去优化指令,而避免去访问内存。
* "":::表示这是个空指令。barrier()不用在此插入一条串行化汇编指令。在后文将讨论什么叫串行化指令。
* __asm__,__volatile__,memory在前面已经解释

323行,计算代码段的长度
monitor_flash_len 是指代码段的长度
在cpu/arm920t/u-boot.lds中定义了程序链接后的各段地址

+-----------+ -> _end
| .bss (ZI) |
+-----------+-> __bss_start
| .data(RW) |
+-----------+
| .text(RO) |
+-----------+ -> _armboot_start 0x33f80000




   325 for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
   326     if ((*init_fnc_ptr)() != 0) {
   327          hang ();
   328     }
   329 }

http://blog.chinaunix.net/u3/93566/showart_2097507.html





   366 /* armboot_start is defined in the board-specific linker script */
   367 mem_malloc_init (_armboot_start - CFG_MALLOC_LEN);
   368
   369 #if defined(CONFIG_CMD_NAND)
   370     puts ("NAND: ");
   371     nand_init(); /* go init the NAND */
   372 #endif

367行,将整个192k的heap区清零

371行,初始化nand flash,要在configs/下的配置头文件里定义CONFIG_CMD_NADN,开启nand相关的
操作。 nand_init()在dreiver/mtd/nand/nand.c中。






   383        /* initialize environment */
   384        env_relocate ();
  
   395        /* IP Address */
   396        gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
   397    
   398        /* MAC Address */
   399        {
   400            int i;
   401            ulong reg;
   402            char *s, *e;
   403            char tmp[64];
   404    
   405            i = getenv_r ("ethaddr", tmp, sizeof (tmp));
   406            s = (i > 0) ? tmp : NULL;
   407    
   408            for (reg = 0; reg < 6; ++reg) {
   409                gd->bd->bi_enetaddr[reg] = s ? simple_strtoul (s, &e, 16) : 0;
   410                if (s)
   411                    s = (*e) ? e + 1 : e;
   412            }
   413

   
    424        }



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


   432        jumptable_init ();
   433    
   434        console_init_r ();    /* fully init console as a device */


   440    
   441        /* enable exceptions */
   442        enable_interrupts ();
   443    
   444        /* Perform network card initialisation if necessary */
   445  


   451    
   452    #ifdef CONFIG_DRIVER_CS8900
   453        cs8900_get_enetaddr (gd->bd->bi_enetaddr);
   454    #endif
   455    
   456    #if defined(CONFIG_DRIVER_SMC91111) || defined (CONFIG_DRIVER_LAN91C96)
   457        if (getenv ("ethaddr")) {
   458            smc_set_mac_addr(gd->bd->bi_enetaddr);
   459        }
   460    #endif /* CONFIG_DRIVER_SMC91111 || CONFIG_DRIVER_LAN91C96 */
   461    
   462        /* Initialize from environment */
   463        if ((s = getenv ("loadaddr")) != NULL) {
   464            load_addr = simple_strtoul (s, NULL, 16);
   465        }

查找环境变量中是否有loadaddr这一项,有的话,就将它的值写入load_addr中
load_addr是加载地址,这在bootm的分析中仍会见到。它表示kernel image 将被
uboot加载到内存的地址。


   466    #if defined(CONFIG_CMD_NET)
   467        if ((s = getenv ("bootfile")) != NULL) {
   468            copy_filename (BootFile, s, sizeof (BootFile));
   469        }
   470    #endif
   471    

   485        /* main_loop() can return to retry autoboot, if so just run it again. */
   486        for (;;) {
   487            main_loop ();
   488        }
   489    
   490        /* NOTREACHED - no way out of command loop except booting */
   491    }


阅读(1026) | 评论(0) | 转发(0) |
0

上一篇:内核启动参数机制学习笔记

下一篇:没有了

给主人留下些什么吧!~~