上接第一阶段跳转语句
ldr pc, _start_armboot
第二阶段流程图
第二阶段的功能:
<1> 初始化本阶段要使用到的硬件设备。
设置时钟、初始化串口。
board_init函数设置MPLL、改变系统时钟,它是开发板相关的函数,在board/samsung/smdk2440/smdk2440.c中实现。值得注意的是board_init函数还保存了机器类型ID,这将在调用内核的时候传递给内核。代码如下:
gd->bd->bi_arch_number = MACH_TYPE_S3C2440; //值为362
串口的初始化函数主要是serial_init,它设置UART控制器,是CPU相关的函数。
<2>检测系统内存映射(memory map)。
对于smdk2440的开发板,其内存分布是明确的,一般内存起始地址为0x3000 0000,大小为64M = 0x0400 0000。代码如下:
int dram_init(void)
{
gd->bd->bi_dram[0] . start = PHYS_SDRAM_1; //即0x3000 0000
gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; //即0x0400 0000
//这两个值都定义在include/configs/smdk2440.h中
}
<3>将内核映像和根文件系统映像从Flash上读到RAM空间中。
<4>为内核设置启动参数。
U-Boot 是通过标记列表向内核传递参数。
setup_memory_tags
setup_commandline_tag
这两个标记列表定义在arch/arm/lib/bootm.c中,需要在定义命令的文件include/configs/smdk2440.h中定义两个命令
#define CONFIG_SETUP_MEMORY_TAGS 1
#define CONFIG_CMDLINE_TAG 1
对于ARM构架的CPU来说,都是通过arch/arm/lib/bootm.c中的do_bootm_linux函数来启动内核的。这个函数中,设置标记列表,最后通过 theKernel = (void (星)(int, int, uint))images->ep;调用内核。其中,theKernel 指向内核存放的地址(对于ARM构架的CPU,通常这个地址是0x3000 8000)。传递的3个参数如下:void (星theKernel)(int zero, int arch, uint params);
R0: 0
R1: 机器类型ID -- gd->bd->bi_arch_number = MACH_TYPE_S3C2440; //值为362
R2: 启动参数标记列表在RAM中的起始地址 0x3000 0100
2。源码解析。
arch/arm/lib/board.c
void start_armboot (void)
{
init_fnc_t **init_fnc_ptr; //定义二级函数指针
char *s;
gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t));
/************************************************************************************************************
定义了全局数据指针,armboot_start的值位于0x3ff80000,且CONFIG_SYS_MALLOC_LEN在
include/configs/smdk2440.h中定义,
#define config_sys_malloc_len (CONFIG_ENV_SIZE + 128 * 1024)
#define CONFIG_ENV_SIZE 0x20000 //128K为256M的Nandflash的块大小,block。
通过以上计算得出 config_sys_malloc_len 的大小为 256k = 0x4 0000。
再来看一下结构体gd_t,位于arch/arm/include/asm/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 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
#ifdef CONFIG_FSL_ESDHC
unsigned long sdhc_clk;
#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;
sizeof(gd_t)=4 + 4 * 6 +