Chinaunix首页 | 论坛 | 博客
  • 博客访问: 309642
  • 博文数量: 60
  • 博客积分: 1451
  • 博客等级: 上尉
  • 技术积分: 710
  • 用 户 组: 普通用户
  • 注册时间: 2009-09-23 23:55
文章分类

全部博文(60)

文章存档

2017年(9)

2014年(1)

2013年(1)

2011年(9)

2010年(35)

2009年(5)

我的朋友

分类: 嵌入式

2009-09-24 18:53:34

从汇编启动代码跳转过来,进入到\u-boot-1.1.4\lib_arm\board.c中start_armboot函数
 
void start_armboot (void)
{
 DECLARE_GLOBAL_DATA_PTR;
 ulong size;
 init_fnc_t **init_fnc_ptr;
 char *s;
#if defined(CONFIG_VFD) || defined(CONFIG_LCD)
 unsigned long addr;
#endif
 /* Pointer is writable since we allocated a register for it */
 gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(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));
 memset (gd->bd, 0, sizeof (bd_t));
 monitor_flash_len = _bss_start - _armboot_start;
 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 ();
 display_flash_config (size);
#ifdef CONFIG_VFD
# ifndef PAGE_SIZE
#   define PAGE_SIZE 4096
# endif
 /*
  * reserve memory for VFD display (always full pages)
  */
 /* bss_end is defined in the board-specific linker script */
 addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
 size = vfd_setmem (addr);
 gd->fb_base = addr;
#endif /* CONFIG_VFD */
#ifdef CONFIG_LCD
# ifndef PAGE_SIZE
#   define PAGE_SIZE 4096
# endif
 /*
  * reserve memory for LCD display (always full pages)
  */
 /* bss_end is defined in the board-specific linker script */
 addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
 size = lcd_setmem (addr);
 gd->fb_base = addr;
#endif /* CONFIG_LCD */
 /* armboot_start is defined in the board-specific linker script */
 mem_malloc_init (_armboot_start - CFG_MALLOC_LEN);
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
 puts ("NAND:");
 nand_init();  /* go init the NAND */
#endif
#ifdef CONFIG_HAS_DATAFLASH
 AT91F_DataflashInit();
 dataflash_print_info();
#endif
 /* initialize environment */
 env_relocate ();
#ifdef CONFIG_VFD
 /* must do this after the framebuffer is allocated */
 drv_vfd_init();
#endif /* CONFIG_VFD */
 /* IP Address */
 gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
 /* MAC Address */
 {
  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 (); /* get the devices list going. */
#ifdef CONFIG_CMC_PU2
 load_sernum_ethaddr ();
#endif /* CONFIG_CMC_PU2 */
 jumptable_init ();
 console_init_r (); /* fully init console as a device */
#if defined(CONFIG_MISC_INIT_R)
 /* miscellaneous platform dependent initialisations */
 misc_init_r ();
#endif
 /* enable exceptions */
 enable_interrupts ();
 /* Perform network card initialisation if necessary */
#ifdef CONFIG_DRIVER_CS8900
 cs8900_get_enetaddr (gd->bd->bi_enetaddr);
#endif
#if defined(CONFIG_DRIVER_SMC91111) || defined (CONFIG_DRIVER_LAN91C96)
 if (getenv ("ethaddr")) {
  smc_set_mac_addr(gd->bd->bi_enetaddr);
 }
#endif /* CONFIG_DRIVER_SMC91111 || CONFIG_DRIVER_LAN91C96 */
 /* Initialize from environment */
 if ((s = getenv ("loadaddr")) != NULL) {
  load_addr = simple_strtoul (s, NULL, 16);
 }
#if (CONFIG_COMMANDS & CFG_CMD_NET)
 if ((s = getenv ("bootfile")) != NULL) {
  copy_filename (BootFile, s, sizeof (BootFile));
 }
#endif /* CFG_CMD_NET */
#ifdef BOARD_LATE_INIT
 board_late_init ();
#endif
#if (CONFIG_COMMANDS & CFG_CMD_NET)
#if defined(CONFIG_NET_MULTI)
 puts ("Net:   ");
#endif
 eth_initialize(gd->bd);
#endif
 /* 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 */
}
 
这个函数一开始声明了一个宏DECLARE_GLOBAL_DATA_PTR,宏的定义在u-boot-1.1.4\include\asm-arm\global_data.h文件中
#define DECLARE_GLOBAL_DATA_PTR     register volatile gd_t *gd asm ("r8")
用gd_t结构体定义了一个指针变量gd,使用用关键字register,指这个变量会频繁使用到,所以用cpu中的寄存器r8存放,提高速度.
gd_t类型在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 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类型的指针变量bd,bd-t类型也在global_data.h中定义
 
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;
现在还不知道这些变量干什么用的,等下要用到时回头再看
接下来定义了一个指针的指针
init_fnc_t **init_fnc_ptr;
其中init_fnc_t在同样的\u-boot-1.1.4\lib_arm\board.c中定义为typedef int (init_fnc_t) (void);这里为什么把(init_fnc_t) (void)定义为int,不太明白.
__asm__ __volatile__("": : :"memory");
下面这段是网上抄来的:
/*------------------------------------------------------------------------------*/
"__asm__"表示后面的代码为内嵌汇编,"asm"是"__asm__"的别名。"__volatile__"表示编译器不要优化代码,后面的指令保留原样,"volatile"是它的别名。括号里面是汇编指令。Memory描述符告知GCC:
1)不要将该段内嵌汇编指令与前面的指令重新排序;也就是在执行内嵌汇编代码之前,它前面的指令都执行完毕
2)不要将变量缓存到寄存器,因为这段代码可能会用到内存变量,而这些内存变量会以不可预知的方式发生改变,因此GCC插入必要的代码先将缓存到寄存器的变量值写回内存,如果后面又访问这些变量,需要重新访问内存。

如果汇编指令修改了内存,但是GCC 本身却察觉不到,因为在输出部分没有描述,此时就需要在修改描述部分增加"memory",告诉GCC 内存已经被修改,GCC 得知这个信息后,就会在这段指令之前,插入必要的指令将前面因为优化Cache 到寄存器中的变量值先写回内存,如果以后又要使用这些变量再重新读取。

使用"volatile"也可以达到这个目的,但是我们在每个变量前增加该关键字,不如使用"memory"方便
/*------------------------------------------------------------------------------*/
 
gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));
这里出现了前面的用gd_t结构体定义的gd指针变量,在这里初始化gd指针到指向的位置.
 memset ((void*)gd, 0, sizeof (gd_t));清零gd指针指向的结构体
gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));初始化bd指针到指向的位置
 memset (gd->bd, 0, sizeof (bd_t));清零bd指针指向的结构体
monitor_flash_len这个变量可能是flash要受保护的长度(如果flash需要受保护的话)
下面这段循环执行init_sequence数组定义的函数:
 for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
  if ((*init_fnc_ptr)() != 0) {
   hang ();
  }
 }
 
 
 
 
阅读(2360) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~