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

 

 

 

 

你可能感兴趣的:(Boot)