U-BOOT第二阶段程序分析(1)

        uboot的第一阶段是用汇编实现的,当然有些情况下还是需要用汇编调用C函数方便些,比如我在移植S32440的uboot的时候由于我需要从nand启动,所以在将uboot这个镜像拷贝到SDRAM中时候就需要初始化好nand flash,然后读取uboot镜像到内存,当第一阶段执行完毕,根据第一阶段最后的分析,程序跳转到了ram中继续执行start_armboot这个C函数。

        下面来看看这个函数主要完成了什么功能。

        1. 首先要说明一个全局数据结构体,用于保存一些全局数据,在uboot第一阶段设置栈指针时,其实就已经为这个结构体在内存中留出了空间,它的地址就是在堆的地址下方,栈的上方。全局数据结构体定义如下所示:
typedef struct global_data {
   bd_t     *bd;
   unsigned long  flags;
   unsigned long  baudrate;
   unsigned long  have_console;  /* serial_init() was called */
   unsigned long  reloc_off;   /* Relocation Offset */
   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
   #if 0
   unsigned long  cpu_clk;   /* CPU clock in Hz!  */
   unsigned long  bus_clk;
   unsigned long  ram_size;   /* RAM size */
   unsigned long  reset_status;  /* reset status register at boot */
   #endif
   void     **jt;     /* jump table */
} gd_t;
        其中的bd_t也是一个结构体,后面可以发现,uboot为bd_t也在内存分配了空间,就在gd_t之下。bd_t的定义如下:
typedef struct bd_info {
    int        bi_baudrate;  /* serial console baudrate */
    unsigned long    bi_ip_addr;  /* IP Address */
    unsigned char    bi_enetaddr[6]; /* Ethernet adress */
    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;

        2. 在start_armboot函数中的第一条就是:DECLARE_GLOBAL_DATA_PTR,这个宏展开就是:
        #define DECLARE_GLOBAL_DATA_PTR     register volatile gd_t *gd asm ("r8")
        DECLARE_GLOBAL_DATA_PTR 定义一个 gd_t 全局数据结构的指针,这个指针存放在指定的寄存器r8 中。这个声明也避免编译器把r8 分配给其它的变量。任何想要访问全局数据区的代码,只要代码开头加入 
“DECLARE_GLOBAL_DATA_PTR”一行代码,然后就可以使用 gd 指针来访问全局数据区了。

你可能感兴趣的:(一步一步学习JZ2440开发板)