start_armboot函数简介
start_armboot函数是一个很长的函数,这个函数在uboot/lib_arm/board.c的第444行开始到908行结束。 这个函数构成了整个uboot启动的第二阶段。
概括来讲,uboot第一阶段主要是初始化了SOC内部一些部件(譬如看门狗、时钟),然后初始化DDR并且完成重定位。而uboot第二阶段就是要初始化剩下的还没被初始化的硬件,主要是SOC外部硬件(譬如iNand、网卡芯片等)、uboot本身的一些东西(uboot的命令、环境变量等)。然后最终初始化完必要的东西进入uboot命令行准备接收命令。
uboot启动后自动运行打印出很多信息(这些信息就是uboot在第一和第二阶段不断进行初始化时,打印出来的信息)。然后uboot进入了倒数bootdelay秒然后执行bootcmd对应的启动命令。
如果没有用户干涉的情况下,uboot会执行bootcmd进入自动启动内核流程(uboot就死掉了);此时用户可以按下回车键打断ubbot的自动启动,进入到uboot的命令行下。然后uboot就一直工作在命令行下。
uboot的命令行就是一个死循环,循环体内不断重复:接收命令,解析命令,执行命令。这就是uboot的最终归宿。
init_fnc_t
void start_armboot (void)
{
init_fnc_t **init_fnc_ptr;
函数开头第一句:typedef int(init_fnc_t) (void); 这是一个函数类型。
init_fnc_ptr是一个二重函数指针。二重指针的类型有两个,一个用来指向一重指针,另一个用来指向指针数组。因此这里的init_fnc_ptr可以用来指向一个函数指针数组。
该内容之后:
/* Pointer is writable since we allocated a register for it */
#ifdef CONFIG_MEMORY_UPPER_CODE /* by scsuh */
ulong gd_base;
定义了一个长整型变量gd_base,它是由gd变量引申而来的。gd变量的定义在include/asm-arm/global_data.h中。定义如下:
#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8")
这个gd其实是一个全局变量,它是一个指针类型,占4字节,后面的asm("r8")是gcc支持的一种语法,意思是把gd放在寄存器r8中。gd是指向gd_t类型变量的指针。
gd_t也定义在include/asm-arm/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;
phys_size_t ram_size; /* RAM size */
unsigned long reset_status; /* reset status register at boot */
#endif
void **jt; /* jump table */
} gd_t;
其中定义了很多全局变量,都是整个uboot使用的;其中有一个bd_t类型的指针,指向一个bd_t类型的变量,这个bd是开发板的板级信息的结构体。里面有不少硬件相关的参数,譬如波特率、IP地址、机器码、DDR内存分布。
内存使用排布
DECLARE_GLOBAL_DATA_PTR只是定义了一个指针,里面的全局变量并没有分配内存,因此需要在使用gd之前分配内