您的位置:首页 > 其它

uboot第二阶段启动过程

2013-05-23 09:31 288 查看
void start_armboot (void)

{

 init_fnc_t **init_fnc_ptr;

 char *s;

 int mmc_exist = 0;

 

 /*全局数据结构初始化*/

 ulong gd_base;

 gd_base = CFG_UBOOT_BASE + CFG_UBOOT_SIZE - CFG_MALLOC_LEN - CFG_STACK_SIZE - sizeof(gd_t);//全局变量地址

 

 gd = (gd_t*)gd_base;

  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,重定位偏移,就是实际定向的位置与编译连接时指定的位置之差,一般为0 */

  unsigned long env_addr; /* Address  of Environment struct,环境参数地址 */

  unsigned long env_valid; /* Checksum of Environment valid? 环境参数CRC检验有效标志*/

  unsigned long fb_base; /* base address of frame buffer,base address of frame buffe */

  void  **jt;  /* jump table,跳转表 */

 } gd_t;
 

 /* compiler optimization barrier needed for GCC >= 3.4 */

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

 memset ((void*)gd, 0, sizeof (gd_t));//全局变量清零

 

 gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));//板子数据变量地址
  typedef struct bd_info {

  int   bi_baudrate; /* serial console baudrate,串口波特率 */

  unsigned long bi_ip_addr; /* IP Address,IP地址 */

  unsigned char bi_enetaddr[6]; /* Ethernet adress,MAC地址 */

  struct environment_s        *bi_env;/*环境变量开始地址*/

  ulong         bi_arch_number; /* unique id for this board,板子唯一ID */

  ulong         bi_boot_params; /* where this board expects params,启动参数 */

  struct    /* RAM configuration,RAM配置 */

  {

  ulong start;

  ulong size;

  }   bi_dram[CONFIG_NR_DRAM_BANKS];

 } bd_t;

 typedef struct environment_s

    {

             unsigned long crc;                    
 

             #ifdef CFG_REDUNDAND_ENVIRONMENT

                   unsigned char flags;             

            #endif

            unsigned char data[ENV_SIZE];          

       } env_t;

 memset (gd->bd, 0, sizeof (bd_t));//板子数据清零

 monitor_flash_len = _bss_start - _armboot_start;//取boot长度

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

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

   hang ();

  }

 }

  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, 打印u-boot信息 */

 #if defined(CONFIG_DISPLAY_CPUINFO)

  print_cpuinfo,  /* display cpu info (and speed) */

 #endif

 #if defined(CONFIG_DISPLAY_BOARDINFO)

  checkboard,  /* display board info,显示板子信息 */

 #endif

 #endif

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

  init_func_i2c,

 #endif

  dram_init,  /* configure available RAM banks,配置可用的RAM */

  display_dram_config,//显示RAM的配置大小

  NULL,

 };

void hang (void)

{

 puts ("### ERROR ### Please RESET the board ###\n");

 for (;;);

}

size = flash_init (); //配置可用flash

typedef struct {

 ulong size;   /* total bank size in bytes  */

 ushort sector_count;  /* number of erase units  */

 ulong flash_id;  /* combined device & manufacturer code */

 ulong start[CFG_MAX_FLASH_SECT];   /* physical sector start addresses */

 uchar protect[CFG_MAX_FLASH_SECT]; /* sector protection status */

#ifdef CFG_FLASH_CFI

 uchar portwidth;  /* the width of the port  */

 uchar chipwidth;  /* the width of the chip  */

 ushort buffer_size;  /* # of bytes in write buffer  */

 ulong erase_blk_tout;  /* maximum block erase timeout  */

 ulong write_tout;  /* maximum write timeout  */

 ulong buffer_write_tout; /* maximum buffer write timeout  */

 ushort vendor;   /* the primary vendor id  */

 ushort cmd_reset;  /* vendor specific reset command */

 ushort interface;  /* used for x8/x16 adjustments  */

 ushort legacy_unlock;  /* support Intel legacy (un)locking */

 uchar manufacturer_id; /* manufacturer id   */

 ushort device_id;  /* device id    */

 ushort device_id2;  /* extended device id   */

 ushort ext_addr;  /* extended query table address  */

 ushort cfi_version;  /* cfi version    */

 ushort cfi_offset;  /* offset for cfi query   */

 ulong   addr_unlock1;  /* unlock address 1 for AMD flash roms  */

 ulong   addr_unlock2;  /* unlock address 2 for AMD flash roms  */

 const char *name;  /* human-readable name                 */

#endif

} flash_info_t; //flash信息结构体

ulong flash_init (void)
{

 int i, j;

 ulong size = 0;

 for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {

 ulong flashbase = 0;

 flash_info[i].flash_id =   (MX_MANUFACT & FLASH_VENDMASK) | (MX_ID_LV640EB & FLASH_TYPEMASK);//flash_info[0].flash_id =0;
 flash_info[i].size = FLASH_BANK_SIZE; //flash_info[0].size = 8M;
 flash_info[i].sector_count = CFG_MAX_FLASH_SECT;
//flash_info[i].sector_count =135;

 memset (flash_info[i].protect, 0, CFG_MAX_FLASH_SECT); //清零
 if (i == 0)

 flashbase = CFG_FLASH_BASE; //flash基地址0x80000000
 else

      panic ("configured too many flash banks!\n");

 for (j = 0; j < flash_info[i].sector_count; j++) {

#if defined(CONFIG_MX_LV640EB)

       if (j <=7) { /* 1st ~ 8th sect size : 8 kb */
       flash_info[i].start[j] =  flashbase + j * BOOT_SECT_SIZE;

    } else { /* 9th ~ 135th sect size : 64 kb */
       flash_info[i].start[j] = flashbase + (j - 7) * MAIN_SECT_SIZE;

    }

 }

  size += flash_info[i].size; //总大小
}

 flash_protect (FLAG_PROTECT_SET,

         CFG_FLASH_BASE,

         CFG_FLASH_BASE + monitor_flash_len - 1,

         &flash_info[0]);

 flash_protect (FLAG_PROTECT_SET,

         CFG_ENV_ADDR,

         CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0]);

 return size;

}

mem_malloc_init (CFG_UBOOT_BASE + CFG_UBOOT_SIZE - CFG_MALLOC_LEN - CFG_STACK_SIZE);//初始化堆空间
mmc_exist = mmc_initialize(gd->bd); //SD、MMC初始化
if (mmc_exist != 0);

nand_init(); //nand初始化

void nand_init(void)

{

 nand_probe(CFG_NAND_BASE);

        if (nand_dev_desc[0].ChipID != NAND_ChipID_UNKNOWN) {

                print_size(nand_dev_desc[0].totlen, "\n");

        }

}

/* initialize environment , 重新定位环境变量*/
 env_relocate ();

void env_relocate (void)

{

 DEBUGF ("%s[%d] offset = 0x%lx\n", __FUNCTION__,__LINE__,

  gd->reloc_off);

#ifdef ENV_IS_EMBEDDED

 /*

  * The environment buffer is embedded with the text segment,

  * just relocate the environment pointer

  */

 env_ptr = (env_t *)((ulong)env_ptr + gd->reloc_off);

 DEBUGF ("%s[%d] embedded ENV at %p\n", __FUNCTION__,__LINE__,env_ptr);

#endif

if (gd->env_valid == 0) {

  set_default_env();

 } else {

  env_relocate_spec ();

 }

 gd->env_addr = (ulong)&(env_ptr->data);

}
 

 serial_initialize(); //串口初始化
 

/*主要是从环境中读IP、MAC,然后赋给gd->bd对应域就OK*/
 /* IP Address , 从环境变量中获取地址*/
 gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");

 /* MAC Address,从环境变量中获取IP地址 */
 {

  int i;

  ulong reg;

  char *s, *e;

  char 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(),创建了devlist,但是只有一个串口设备注册在内。显然,devlist中的设备都是可以做为console的。*/

 devices_init (); /* get the devices list going.设备初始化 */

int devices_init (void)

{

#ifndef CONFIG_ARM     /* already relocated for current ARM implementation */

 ulong relocation_offset = gd->reloc_off;

 int i;

 /* relocate device name pointers */

 for (i = 0; i < (sizeof (stdio_names) / sizeof (char *)); ++i) {

  stdio_names[i] = (char *) (((ulong) stdio_names[i]) +

      relocation_offset);

 }

#endif

 /* Initialize the list */

 devlist = ListCreate (sizeof (device_t)); //创建设备列表

 if (devlist == NULL) {

  eputs ("Cannot initialize the list of devices!\n");

  return -1;

 }

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

 i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);//初始化i2c接口,i2c没有注册到devlist中去

#endif
 return (0);

}

 

 jumptable_init (); //跳转初始化表
 
/*查看环境参数stdin,stdout,stderr中对标准IO的指定的设备名称,再按照环境指定的名称搜索devlist,将搜到的设备指针赋给标准IO数组stdio_devices[]。置gd->flag标志

GD_FLG_DEVINIT。这个标志影响putc,getc函数的实现,未定义此标志时直接由串口serial_getc和serial_putc实现,定义以后通过标准设备数组stdio_devices[]中的putc和getc来实现IO

为什么要使用devlist,std_device[]?
为了更灵活地实现标准IO重定向,任何可以作为标准IO的设备,如USB键盘,LCD屏,串口等都可以对应一个device_t的结构体变量,只需要实现getc和putc等函数,就能加入到devlist列表中去,也就可
以被assign为标准IO设备std_device中去。如函数
int console_assign (int file, char *devname); /* Assign the console 重定向标准输入输出*/
这个函数功能就是把名为devname的设备重定向为标准IO文件file(stdin,stdout,stderr)。其执行过程是在devlist中查找devname的设备,返回这个设备的device_t指针,并把指针值赋给std_device[file]。
*/

 console_init_r (); /* fully init console as a device, 完整地初始化控制台设备*/

/* enable exceptions ,使能外部中断,由于CONFIG_USE_IRQ没有定义,空实现*/
 enable_interrupts ();

 cs8900_get_enetaddr (gd->bd->bi_enetaddr);
/*设置CS8900的MAC地址。*/

 /* 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 ();

 puts ("Net:   ");

/*初始化以太网*/
 eth_initialize(gd->bd);

 debug ("Reset Ethernet PHY\n");

 reset_phy();

 puts("IDE:   ");

 ide_init();

 /* main_loop() can return to retry autoboot, if so just run it again. */

 for (;;) {

  main_loop ();

 }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: