Uboot啟動過程原始碼分析之第二階段
UBoot的最終目標是啟動核心
1.從Flash中讀出核心
2.啟動核心
通過呼叫lib_arm/board.c中的start_armboot函式進入uboot第二階段
第二階段總結圖
typedef struct global_data { bd_t *bd; unsigned long flags; unsigned long baudrate; unsigned long cpu_clk; /* CPU clock in Hz! */ unsigned long have_console; /* serial_init() was called */ unsigned long ram_size; /* RAM size */ unsigned long reloc_off; /* Relocation Offset */ unsigned long env_addr; /* Address of Environment struct */ unsigned long env_valid; /* Checksum of Environment valid */ #if defined(CONFIG_POST) || defined(CONFIG_LOGBUFFER) unsigned long post_log_word; /* Record POST activities */ unsigned long post_init_f_time; /* When post_init_f started */ #endif void **jt; /* Standalone app jump table */ } gd_t;
gd_t定義在include/asm-arm/global_data.h中。gd_t中定義了很多全域性變數,都是整個uboot使用的;其中有一個bd_t型別的指標,指向一個bd_t型別的變數,
這個bd是開發板的板級資訊的結構體,裡面有不少硬體相關的引數,譬如波特率、IP地址、機器碼(bi_arch_number)、uboot給kernel傳參時引數所在的地址(bi_boot_params),
DDR記憶體分佈(bi_dram)
#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8")
定義了一個全域性變數名字叫gd,這個全域性變數是一個指標型別,佔4位元組。用volatile修飾表示可變的,用register修飾表示這個變數要儘量放到暫存器中,
後面的asm(“r8”)是gcc支援的一種語法,意思就是要把gd放到暫存器r8中。
為什麼要定義為register?
因為這個全域性變數gd(global data的簡稱)是uboot中很重要的一個全域性變數,這個gd在程式中經常被訪問,因此放在register中提升效率。因此純粹是執行效率方面考慮,和功能要求無關。並不是必須的。
DECLARE_GLOBAL_DATA_PTR只能定義了一個指標,也就是說gd裡的這些全域性變數並沒有被分配記憶體,我們在使用gd之前要給他分配記憶體,否則gd也只是一個野指標而已。gd和bd需要記憶體,記憶體當前沒有被人管理(因為沒有作業系統統一管理記憶體),大片的DDR記憶體散放著可以隨意使用(只要使用記憶體地址直接去訪問記憶體即可),在uboot中需要有一個整體規劃. 如下:
U-Boot啟動核心時要給核心傳遞引數,這時就要使用gd_t,bd_t結構體中的資訊來設定標記列表。