uboot第2階段分析 start_armboot

通過前面的分析,知道第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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章