zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    使用openssl实现ECDSA签名以及验证功能(附完整测试源码)
    【转载】浅谈Linux内存管理机制
    【转载】Abstract Factory Step by Step --- 抽象工厂
    【转载】动态规划:从新手到专家
    Windows Container 和 Docker:你需要知道的5件事
    十年
    Docker,容器,虚拟机和红烧肉
    新的用户故事待办列表就是一副地图
    MarkDown/reST 文档发布流水线
    docker4dotnet #5 使用VSTS/TFS搭建基于容器的持续交付管道
  • 原文地址:https://www.cnblogs.com/plinx/p/3055752.html
Copyright © 2011-2022 走看看