Boot+loader:在操作系统运行之前运行的一段代码,实现是非常依赖具体的硬件(CPU和外设配置的不同)。
Boot:启动系统,初始化硬件设备,建立内存空间映射图,将系统的软硬件软件带到一个合适的状态。
Loader:将操作系统内核文件加载至内存,之后跳转到内核所在地址运行。
==========================================
u-boot 启动,执行的第一阶段:
第一阶段主要操作:
1.关闭看门狗
2.初始化系统时钟(通过外接低频晶振,PLL锁相环,升1G)
3.初始化外接内存的控制器(S5PV210SDRAM控制器)
4.初始化串口控制器(PCLK=66.5MHZ)
5.初始化Nand flash控制器(HCLK=133MHZ)
要使u-boot.bin前8K代码能在CPU内部的SRAM中运行,必须保证8K的代码是位置无关码(相对跳转指令b或bl,不能绝对跳转)
====================================
u-boot分析:
源文件board.c(start_armboot()函数执行第二阶段的初始化):初始化开发板外设的相关信息到对应的结构体中。
gd_t:uboot用来保存全局信息的结构体。
#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gdasm ("r8")
申请gd放到CPU内部的寄存器中,不一定成功。目的是能快速访问它里面的内容,结构体的内容还是在内存。
arm-linux-gcc -g -Os
-fno-strict-aliasing -fno-common
-ffixed-r8 (-ffixed选项:把r8留出来)
-msoft-float -D__KERNEL__ -DTEXT_BASE=0xc3e00000
结构体定义如下:
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 */
phys_size_t 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;
-------------------------------------------------------
bd_t:uboot用来保存开发板信息的结构体
typedef struct bd_info {
unsignedlong bi_baudrate;
unsignedlong bi_ip_addr;
unsignedchar bi_enetaddr[6];
unsignedchar bi_phy_id[4];
structenvironment_s *bi_env;
unsignedlong bi_board_number;
void *bi_boot_params;
struct{
unsignedlong start;
unsignedlong size;
} bi_dram[CONFIG_NR_DRAM_BANKS];
unsignedlong bi_flashstart;
unsignedlong bi_flashsize;
unsignedlong bi_flashoffset;
} bd_t;
====================================
int board_init(void)
{
/* …… */
gd->bd->bi_arch_number= MACH_TYPE;//开发板架构ID号->2456:uboot传递给内核的启动参数
gd->bd->bi_boot_params= (PHYS_SDRAM_1+0x100);//uboot在引导Linux内核时,会向Linux内核传递参数,此处初始化的是参数存放的地址,0x20000100
/* …… */
}
int dram_init (void) /* configure available RAM banks 指定外部DRAM内存大小信息*/
{
gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
return 0;
}
//初始化完成各个参数后,调用主函数:
/* main_loop() can return to retry autoboot, if so just runit again. */
for (;;) {
main_loop ();
}
====================================
修改 u-boot 的环境变量,启动内核并加载NFS文件:
1)bootcmd: 存放内核自启动的命令
2)bootm:执行内存中的内核代码
bootcmd tftp 50008000 zImage; bootm 50008000//通过tftp 方式下载内核到50008000地址,并启动内核
a.执行bootm命令,即执行bootm命令对应的处理函数do_bootm( )
b.do_bootm( ) 函数调用do_bootm_linux()
c.do_bootm_linux函数调用theKernel(0,2456/* 开发板arch的ID号 */, 0x20000100)
void (*theKernel)(intzero, int arch, uint params);
3)bootargs:挂载文件系统(传递给内核的命令行参数)
NFS文件挂载方式命令行设置:
setenv bootargs
root=/dev/nfs //挂载nfs文件系统
init=/linuxrc //内核启动执行的第一个进程
console=ttySAC0
nfsroot=192.168.1.8:/opt/rootfs //nfs文件所在路径
ip=192.168.1.6:192.168.1.8:192.168.1.1:255.255.255.0::eth0:on