S3C6410之uboot回炉再造(7)C环境的入口

  上一部分讲到 uboot 跳转到 start_armboot 处执行(中间插了一篇 异常中断处理)。

  这次主要是记录 start_armboot 的实现。

  文件为 /lib_arm/board.c

 

  1、参数声明

  1 void start_armboot (void)
  2 {
  3     init_fnc_t **init_fnc_ptr;        //这里实际上是创建数组指针
           //指向的数组为 start_armboot 之前的 init_sequence 数组
  4     char *s;
  5 #if defined(CONFIG_VFD) || defined(CONFIG_LCD)
  6     unsigned long addr;
  7 #endif

 

  2、两个结构体与内存屏障

  8 
  9     /* Pointer is writable since we allocated a register for it */
 10     gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t));
 11     /* compiler optimization barrier needed for GCC >= 3.4 */
 12     __asm__ __volatile__("": : :"memory");

  这里有两个结构体要展开

  1)uboot所调用的配置信息,文件为/include/asm-arm/Global_data.h

typedef    struct    global_data {
    bd_t        *bd;      
    unsigned long    flags;
    unsigned long    baudrate;
    unsigned long    have_console;    /* serial_init() was called */
    unsigned long    env_addr;    /* Address  of Environment struct */
    unsigned long    env_valid;    /* Checksum of Environment valid? */
    unsigned long    fb_base;    /* base address of frame buffer */
#ifdef CONFIG_VFD
    unsigned char    vfd_type;    /* display type */
#endif
#ifdef CONFIG_FSL_ESDHC
    unsigned long    sdhc_clk;
#endif
#if 0
    unsigned long    cpu_clk;    /* CPU clock in Hz!        */
    unsigned long    bus_clk;
    phys_size_t    ram_size;    /* RAM size */
    unsigned long    reset_status;    /* reset status register at boot */
#endif
    void        **jt;        /* jump table */
} gd_t;

  2)板子所调用的板级配置信息,文件为/include/asm-arm/U-boot.h

typedef struct bd_info {
    int            bi_baudrate;    /* serial console baudrate */
    unsigned long    bi_ip_addr;    /* IP Address */
    struct environment_s           *bi_env;
    ulong            bi_arch_number;    /* unique id for this board */
    ulong            bi_boot_params;    /* where this board expects params */
    struct                /* RAM configuration */
    {
    ulong start;
    ulong size;
    }            bi_dram[CONFIG_NR_DRAM_BANKS];
} bd_t;

  这里的 gd 实际指向了一个地址,地址位置可以看下图

  注意,这里为小端模式

  _bss_start    
     |
  TEXT/DATA       
        |        // = 0x100000 + 0x4000
CONFIG_SYS_MALLOC_LEN 
        |        // = sizeof(gd_t)
      gd_t            // gd 实际指向的地址
        |        // = sizeof(bd_t)
    bd_t       // gd_t 的第一部分就是 bd_t
     |
_armboot_start     // 定义在 start.S 中
     |
    STACK      // IRQ_STACK_START FIQ_STACK_START

  然后是内存屏障

 12     __asm__ __volatile__("": : :"memory");

  简单理解起来就是:禁止编译器优化此处的汇编代码。

  这样做,可以有效防止 编译器将当前的寄存器的值 直接替换在代码中。

  这行代码大量地使用在内存屏障函数中,例如 mb()函数组。

  更详细的介绍可以参详

http://blog.sina.com.cn/s/blog_7e741b830100wz1f.html

 

  3、分配空间

 13 
 14     memset ((void*)gd, 0, sizeof (gd_t));      //清空 gd 的对应空间
 15     gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));   //设置 bd 指向地址
 16     memset (gd->bd, 0, sizeof (bd_t));        //清空 bd 的对应空间
 17 
 18     gd->flags |= GD_FLG_RELOC;  
      // #define GD_FLG_RELOC 0x00001 /* Code was relocated to RAM*/
 19 
 20     monitor_flash_len = _bss_start - _armboot_start;

 

  4、初始化

 21 
 22     for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
 23         if ((*init_fnc_ptr)() != 0) {
 24             hang ();
 25         }
 26     }

  这里的 hang 其实是死循环,函数如下

void hang (void)
{
    puts ("### ERROR ### Please RESET the board ###\n");
    for (;;);
}

  意味着如果有初始化函数不存在,或者初始化失败(返回不为0),则出错。

 

  5、清空 code 区

 27 
 28     /* armboot_start is defined in the board-specific linker script */
 29     mem_malloc_init (_armboot_start - CONFIG_SYS_MALLOC_LEN,
 30             CONFIG_SYS_MALLOC_LEN);

  此处有

void mem_malloc_init(ulong start, ulong size)
{
    mem_malloc_start = start;
    mem_malloc_end = start + size;
    mem_malloc_brk = start;

    memset((void *)mem_malloc_start, 0, size);
}

 

  6、之后有大量的可配置项,这些可配置项的内部实现都很简单清晰,所以仅列出标题了

 32 #ifndef CONFIG_SYS_NO_FLASH
 37 #ifdef CONFIG_VFD
 50 #ifdef CONFIG_LCD
 75 #ifdef CONFIG_HAS_DATAFLASH

 

  7、变量搬移

 79 
 80     /* initialize environment */
 81     env_relocate ();

  具体实现在 /common/Env_common.c 中

 

  8、可配置项

 83 #ifdef CONFIG_VFD
 88 #ifdef CONFIG_SERIAL_MULTI

 

  9、这一段代码量较长、不继续深入

  主要功能看代码自注

 91 
 92     /* IP Address */
 93     gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
 94 
 95     stdio_init ();    /* get the devices list going. */
 96 
 97     jumptable_init ();

 

  10、可配置项

 99 #if defined(CONFIG_API)

 

  11、控制台初始化

104     console_init_r ();    /* fully init console as a device */

 

  12、可配置项

106 #if defined(CONFIG_ARCH_MISC_INIT)
110 #if defined(CONFIG_MISC_INIT_R)

  

  13、使能中断

114 
115     /* enable exceptions */
116     enable_interrupts ();

 

  14、可配置项

119 #ifdef CONFIG_DRIVER_TI_EMAC
129 #if defined(CONFIG_DRIVER_SMC91111) || defined (CONFIG_DRIVER_LAN91C96)

 

  16、

137 
138     /* Initialize from environment */
139     if ((s = getenv ("loadaddr")) != NULL) {
140         load_addr = simple_strtoul (s, NULL, 16);
141     }

 

  17、可配置项

142 #if defined(CONFIG_CMD_NET)
148 #ifdef BOARD_LATE_INIT
152 #ifdef CONFIG_GENERIC_MMC
157 #ifdef CONFIG_BITBANGMII
160 #if defined(CONFIG_CMD_NET)
161 #if defined(CONFIG_NET_MULTI)

 

  18、网卡设置

164     eth_initialize(gd->bd);

 

  19、可配置项

165 #if defined(CONFIG_RESET_PHY_R)

 

  20、进入主循环

170     /* main_loop() can return to retry autoboot, if so just run it again. */
171     for (;;) {
172         main_loop ();
173     }
174 
175     /* NOTREACHED - no way out of command loop except booting */

  文件路径为 /common/Main.c

 

 

 

 

posted on 2013-05-03 00:49  plinx  阅读(1204)  评论(0编辑  收藏  举报

导航