Chinaunix首页 | 论坛 | 博客
  • 博客访问: 500206
  • 博文数量: 104
  • 博客积分: 3045
  • 博客等级: 少校
  • 技术积分: 1230
  • 用 户 组: 普通用户
  • 注册时间: 2008-02-29 10:18
文章分类

全部博文(104)

文章存档

2011年(72)

2010年(1)

2009年(1)

2008年(30)

分类:

2008-04-06 13:23:47

由汇编部分转入C语言后第一个执行这个文件中的start_armboot ()函数。

部分代码分析如下:

typedef int (init_fnc_t) (void);   // 定义函数类型

// 下面为初始化函数定义
init_fnc_t *init_sequence[] = {
 cpu_init,    // cp/pxa/cpu.c文件, 执行CPU相关的初始化.
 board_init,   // board/psbec270/board.c文件, 执行board相关的初始化.
 interrupt_init,  // cp/pxa/interrupt.c文件, 中断初始化, 一般不需要使用中断.
 env_init,    // 环境变量初始化
 init_baudrate,  /* initialze baudrate settings */
 serial_init,   /* serial communications setup */
 console_init_f,  /* stage 1 init of console */
 display_banner,  /* say that we are here */
 dram_init,   /* configure available RAM banks */
 display_dram_config,
#if defined(CONFIG_VCMA9)
 checkboard,
#endif
 NULL,
};

// 在start_armboot()函数中实现如下代码, 用于执行上面定义的初始函数.
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
  if ((*init_fnc_ptr)() != 0) {
   hang ();
  }
 }

 接下来就是一些系统中用到的环境,变量等初始化,最后进入主循环, 下面是具体分析:
typedef int (init_fnc_t) (void);

init_fnc_t *init_sequence[] = {
 cpu_init,    /* basic cpu dependent setup */
 board_init,   /* basic board dependent setup */
 interrupt_init,   /* set up exceptions */
 env_init,    /* initialize environment */
 init_baudrate,  /* initialze baudrate settings */
 serial_init,   /* serial communications setup */
 console_init_f,  /* stage 1 init of console */
 display_banner,  /* say that we are here */
 dram_init,   /* configure available RAM banks */
 display_dram_config,
 NULL,
};

// 全局数据结构信息
typedef struct global_data {
 bd_t  *bd;       // 开发板相关参数
 unsigned long flags;
 unsigned long baudrate;   // 串行口通讯速率
 unsigned long have_console;  // console_init_f()中使用控制台
 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
 void  **jt;       // jumptable_init()初始化
} gd_t;

// 开发板相关的信息
typedef struct bd_info {
    int bi_baudrate;      // serial通讯接口的速率
    unsigned long bi_ip_addr;   // 本机IP地址
    unsigned char bi_enetaddr[6];   // MAC地址
    struct environment_s *bi_env;   // 环境变量
    ulong bi_arch_number;    // 开发板ID
/*
   该变量标识每一种开发板相关的ID号, 对于本系统来说:
gd->bd->bi_arch_number = MACH_TYPE_MAINSTONE;

  该值将传递给内核, 如果这个参数与内核配置的不相同, 那么内核启动解压缩完成后将出现”Error: a”错误, 提示用户这个是体系结构参数传递的不正确. 由于本开发板内核是从Intel的mainstone开发板内核修改而来, 内部的配置都是使用的MAINSTONE开发板的参数, 故这里将ARCH设置为MACH_TYPE_MAINSTONE.
*/
    ulong bi_boot_params;   // Uboot传递给linux内核的参数保存地址
/*
 该变量在board/psbec270/psbec270.c中的int board_init(void)中赋值, 这个值的定义是:
gd->bd->bi_boot_params = 0xA0000100;
该变量保存了Uboot传递给linux的参数的地址, 在linux的引导过程中,
head.s文件中没有对传递进来的参数进行处理, 在init/main.c文件中的
start_kernel函数中, 进行解析.
*/
    struct       // RAM configuration
    {
  ulong start;
  ulong size;
    } bi_dram[CONFIG_NR_DRAM_BANKS];
     /*
      SDram设置, 可以存在多个bank, 由宏定义
    CONFIG_NR_DRAM_BANKS决定.
      board/psbec270/psbec270.c文件中dram_init()执行RAM初始化 
       int dram_init(void)
    gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
    gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
     */
} bd_t;

void start_armboot (void)
{
 DECLARE_GLOBAL_DATA_PTR;
 // #define DECLARE_GLOBAL_DATA_PTR  register volatile gd_t *gd asm ("r8")
 
 ulong size;
 init_fnc_t **init_fnc_ptr;
 char *s;

 // gd分配内存在空闲区(直接地址引用)
 gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));
 /* compiler optimization barrier needed for GCC >= 3.4 */
 __asm__ __volatile__("": : :"memory");
// 给gd分配内存, 这里是在uboot使用的前面, 属于空闲内存.
 memset ((void*)gd, 0, sizeof (gd_t));   
// bd分配内存在空闲区, gd的低端(直接地址引用)
 gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));  
 memset (gd->bd, 0, sizeof (bd_t));

 monitor_flash_len = _bss_start - _armboot_start;// 受监控flash空间大小
 
 // 初始化函数, 见上面定义的函数数组, 其中有几个是开发板相关的.
 for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
  if ((*init_fnc_ptr)() != 0) {
   hang ();
  }
 }

 /* configure available FLASH banks */
 size = flash_init ();    // flash初始化
 display_flash_config (size);

 /* armboot_start is defined in the board-specific linker script */
 // malloc使用的内存空间
 mem_malloc_init (_armboot_start - CFG_MALLOC_LEN);

// 如果有nandflash的话就在下面的代码中进行初始化.
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
 puts ("NAND:");
 nand_init();  /* go init the NAND */
#endif
 env_relocate (); // 执行环境初始化
 
 gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr"); // 环境变量中获得本机IP
 
 // 获得Mac地址
 {
  int i;
  ulong reg;
  char *s, *e;
  uchar tmp[64];

  i = getenv_r ("ethaddr", tmp, sizeof (tmp));
  s = (i > 0) ? tmp : NULL;

  for (reg = 0; reg < 6; ++reg) {
   gd->bd->bi_enetaddr[reg] = s ? simple_strtoul (s, &e, 16) : 0;
   if (s)
    s = (*e) ? e + 1 : e;
  }
 }

 devices_init ();   // 设备初始化
 jumptable_init ();   // 给gd->jt分配内存, 然后加入相关的执行函数
 console_init_r ();   // fully init console as a device

 enable_interrupts ();
 /* Initialize from environment */
 if ((s = getenv ("loadaddr")) != NULL) {
  load_addr = simple_strtoul (s, NULL, 16);
 }
 if ((s = getenv ("bootfile")) != NULL) {
  copy_filename (BootFile, s, sizeof (BootFile));
 }

 board_late_init ();

 /* main_loop() can return to retry autoboot, if so just run it again. */
 for (;;) {    // 进入主循环后等待命令
  main_loop ();
 }

 /* NOTREACHED - no way out of command loop except booting */
}
阅读(1819) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~