您的位置:首页 > 其它

uboot第2阶段分析 start_armboot

2010-12-28 20:01 549 查看
通过前面的分析,知道第2阶段代码主要是start_armboot,首先我们先介绍几个比较重要的结构体。这里主要是对start_armboot中的流程做具体的分析,我的uboot-2009-06.至于具体的代码分析将在后面的文章中介绍。

1.gd_t全局数据结构,主要保存了uboot的配置信息。include/asm-arm/global_data.h中定义:

typedef struct global_data {

 bd_t  *bd;//板子相关的结构体

 unsigned long flags;//

 unsigned long baudrate;//波特率

 unsigned long have_console; /* 串口调用*/

 unsigned long reloc_off; /* Relocation Offset 重定位偏移*/

 unsigned long env_addr; /* 环境变量基址*/

 unsigned long env_valid; /* Checksum of Environment valid? */

 unsigned long fb_base; /*帧缓冲基地址*/

#ifdef CONFIG_VFD

 unsigned char vfd_type; /* display type */

#endif

#if 0

 unsigned long cpu_clk; /* cpu频率!  */

 unsigned long bus_clk;/*总线频率*/

 phys_size_t ram_size; /* RAM大小设置,64M*/

 unsigned long reset_status; /* 重新设置状态地址*/

#endif

 void  **jt;  /* jump table 保存着些函数的入口地址,在common/Exports.c中进行填充*/

} gd_t;

#define DECLARE_GLOBAL_DATA_PTR     register volatile gd_t *gd asm ("r8")

这个声明告诉编译器使用寄存器r8来存储gd_t类型的指针gd,即这个定义声明了一个指针,并且指明了它的存储位置。

register表示变量放在机器的寄存器

volatile用于指定变量的值可以由外部过程异步修改

这个指针在board.c中初始化。

2.bd_t板子数据结构体,主要保存与板子相关的信息。定义在include/asm-arm/u-boot.h中

typedef struct bd_info {

    int   bi_baudrate; /* 串口频率*/

    unsigned long bi_ip_addr; /*IP地址*/

    struct environment_s        *bi_env;环境变量指针

    ulong         bi_arch_number; /* 板子ID*/

    ulong         bi_boot_params; /* 启动参数存放地址*/

    struct    /* RAM configuration */

    {

 ulong start;

 ulong size;

    }   bi_dram[CONFIG_NR_DRAM_BANKS];//SDRAM的大小,此处的CONFIG_NR_DRAM_BANKS在smdk2410.h中宏定义

} bd_t;

3.初始化函数队列

typedef int (init_fnc_t) (void);定义函数指针;

下面是函数指针数组

init_fnc_t *init_sequence[] = {

 cpu_init,  /* CPU初始化,定义在cpu/arm920t/cpu.c*/

#if defined(CONFIG_ARCH_CPU_INIT)

 arch_cpu_init,  /* 相关体系结构CPU初始化cpu/.../arch/cpu.c */

#endif

 board_init,  /* 相关板子初始化board/sbc2410x/sbc2410.c*/

 interrupt_init,  /* 中断初始化cpu/arm920t/ s3c24x0/interrupts.c*/

 env_init,  /* 环境变量初始化*/

 init_baudrate,  /* 初始化波特率*/

 serial_init,  /* 串口初始化drivers/serial/serial.c*/

 console_init_f,  /* stage 1 init of console ???不知何意*/

 display_banner,  /* say that we are here */

#if defined(CONFIG_DISPLAY_CPUINFO)

 print_cpuinfo,  /* 打印CPU信息 */

#endif

#if defined(CONFIG_DISPLAY_BOARDINFO)

 checkboard,  /* 显示板块信息*/

#endif

#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)

 init_func_i2c,IIC初始化函数

#endif

 dram_init,  /* configure available RAM banks */

#if defined(CONFIG_CMD_PCI) || defined (CONFIG_PCI)

 arm_pci_init,

#endif

 display_dram_config,存储器件初始化

 NULL,

}

OK现在开始分析start_armboot,这里只分析流程。

void start_armboot (void)

{

 init_fnc_t **init_fnc_ptr;//定义二级函数指针

 char *s;

#if defined(CONFIG_VFD) || defined(CONFIG_LCD)//如果定义了Lcd或者VFD,则指定帧缓冲的地址

 unsigned long addr;

#endif

 /* Pointer is writable since we allocated a register for it */

/*定义了全局数据指针,见上1,_armboot_start的值
位0x3ff80000,且CONFIG_SYS_MALLOC_LEN在smdk2410.h中定义,经过计算可知道
config_sys_malloc_len大小为0x30000,sizeof(gd_t)=4+4*7+4=36=0x24.故gd所指向地址
0x3ff80000-0x30000-0x24约为ox3ff50000*/

 gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t));

 /*下面这局话请参考内存屏障*/

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

 memset ((void*)gd, 0, sizeof (gd_t));

/*对板块信息指针初始化*/

gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));

 memset (gd->bd, 0, sizeof (bd_t));

/*设置当前uboot标志位已经重定位*/

gd->flags |= GD_FLG_RELOC;

monitor_flash_len = _bss_start - _armboot_start;//uboot镜像文件大小

/*初始化函数*/

 for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {

  if ((*init_fnc_ptr)() != 0) {

   hang ();

  }

 }

//flash初始化以及打印其信息

display_flash_config (flash_init ());

//malloc内存空间清零

mem_malloc_init (_armboot_start - CONFIG_SYS_MALLOC_LEN);

//如果定义了nandflash,则对nandflash初始化

#if defined(CONFIG_CMD_NAND)

 puts ("NAND:  ");

 nand_init();  /* go init the NAND */

#endif

//环境初始化

env_relocate ();

serial_initialize();

//设置IP地址,以及设备初始化

gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");

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

 jumptable_init ();//初始化跳转表,对gd中的jt(函数跳转表)数组进行初始化,其中保存着一些函数的入口地址

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

misc_init_r ();

//中断使能

enable_interrupts ();

//得到当前网卡物理地址

cs8900_get_enetaddr ();

//设置网卡

eth_initialize(gd->bd)

for (;;) {

  main_loop ();

 }

}

 

文章来自:http://blog.csdn.net/fangbing007/archive/2009/10/03/4628402.aspx
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: