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结构体中的信息来设置标记列表。