- 略过所有没有定义的宏定义
- 这是uboot第二阶段的入口函数
- 函数位于
lib_arm/board.c
中
DECLARE_GLOBAL_DATA_PTR
#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8")
- 定义了一个要放到寄存器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
void **jt; /* jump table */
} gd_t;
- 这就是板子的一些配置文件。
bd->bi_arch_number
是板子的机器码bd->bi_boot_params
是传给linux的启动参数的地址
内存分布
#ifdef CONFIG_MEMORY_UPPER_CODE
ulong gd_base;
gd_base = CFG_UBOOT_BASE + CFG_UBOOT_SIZE - CFG_MALLOC_LEN - CFG_STACK_SIZE - sizeof(gd_t);
#ifdef CONFIG_USE_IRQ
gd_base -= (CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ);
#endif //CONFIG_USE_IRQ
gd = (gd_t*)gd_base;
#else //CONFIG_MEMORY_UPPER_CODE
gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));
#endif //CONFIG_MEMORY_UPPER_CODE
/* 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));
- 只有第一次定义的gd_base对我们来说是有效的
- 变量gd_base指的gd在DDR中分配内存的起始地址
gd_base = CFG_UBOOT_BASE + CFG_UBOOT_SIZE - CFG_MALLOC_LEN - CFG_STACK_SIZE - sizeof(gd_t)
最后的结果是0xc3e00000+(2x1024x1024) - 912*1024 - 512*1024 - 36 = 0xc3e9bfdc
- 直接将gd_base赋值给全局变量的gd
- gd->bd在gd往下
sizeof(bd_t)
的位置 - 结合uboot启动第一阶段最后一次sp指针的设置,最后的内存结构如下
硬件初始化
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 ();
}
}
- 为全局变量
monitor_flash_len
赋值 init_fnc_ptr
的定义为init_fnc_t **init_fnc_ptr
,而init_func_t的定义为typedef int (init_fnc_t) (void);
这表明init_func_t是一个接收参数是void而返回值是int的函数类型init_sequence
里定义了一系列函数,此代码的功能就是执行这里面的初始化函数,如果有任何一个返回的函数返回值不为0,则串口输出### ERROR ### Please RESET the board ###
,然后进入死循环