start_armboot
cpu_init //初始化IRQ/FIQ模式的栈
board_init
/* 设置时钟 */
clk_power->MPLLCON = ((M_MDIV << 12) + (M_PDIV << 4) + M_SDIV);
设置IO管脚
gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;//机器ID
gd->bd->bi_boot_params = 0x30000100;//传参的存放地址
icache_enable()
dcache_enable();
interrupt_init //初始化定时器
env_init //检查flash上的环境参数是否有效
init_baudrate //以下三个函数用于初始化串口
serial_init
console_init_f
dram_init //检测系统内存映射
gd->bd->bi_dram[0].start = PHYS_SDRAM_1; //内存起始地址
gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; //内存大小
flash_init //识别norflash并初始化
nand_init //识别nandflash
env_relocate //将环境变量读入内存有效位置
main_loop //根据环境变量启动内核
用图形化具体描述为:
我们看到最后启动内核的时候用到u-boot的命令,我们下面来说一下这些命令的格式:
uboot中每个命令都通过U_BOOT_CMD宏来定义,格式如下:
#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \
各参数的意义如下:
name:命令的名字,注意,它不是一个字符串(不要用双引号括起来)
maxargs:最大的参数个数
rep:命令是否可重复,可重复是指运行一个命令后,下次敲回车即可再次运行
cmd:对应的函数指针,类型为:*(cmd)(struct cmd_tbl_s *,int, int, char *[])
usage:简短的使用说明,这是个字符串
help:较详细的命令说明
#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \
cmd_tbl_t __u_boot_cmd_##name Struct_Section = {#name, maxargs, rep, cmd, usage, help}
#define Struct_Section __attribute__ ((unused,section (".u_boot_cmd")))
比如对于bootm其定义为:
U_BOOT_CMD(
bootm,
CFG_MAXARGS,
1,
do_bootm,
"bootm - boot application image from memory\n",
"[addr [arg ...]]\n - boot application image stored in memory\n"
"\tpassing arguments 'arg ...'; when booting a Linux kernel,\n"
"\t'arg' can be the address of an initrd image\n"
#ifdef CONFIG_OF_FLAT_TREE
"\tWhen booting a Linux kernel which requires a flat device-tree\n"
"\ta third argument is required which is the address of the of the\n"
"\tdevice-tree blob. To boot that kernel without an initrd image,\n"
"\tuse a '-' for the second argument. If you do not pass a third\n"
"\ta bd_info struct will be passed instead\n"
#endif
);
宏展开就是:
cmd_tbl_t
__u_boot_cmd_
bootm
__attribute__
((unused,section (".u_boot_cmd")))
=
{
bootm
,
CFG_MAXARGS
, 1,
do_bootm
, string1
, string2}
对于每一个用
U_BOOT_CMD定义的命令,其实都是在
".u_boot_cmd"段中定义一个
cmd_tbl_t
结构体,连接脚本里面有如下代码:
__u_boot_cmd_start = .;
.u_boot_cmd : { *(.u_boot_cmd) }
__u_boot_cmd_end = .;
程序中就是根据命令的名字在
__u_boot_cmd_start
~
__u_boot_cmd_end
中找到其对应的
cmd_tbl_t
结构体,然后调用其函数!
最后我们来总结一下,命令的实现与应用:
我们用
U_BOOT_CMD宏定义一个命令,包括命令名、对应的函数,以及说明!定义的这个命令被存放在
__u_boot_cmd_start
~
__u_boot_cmd_end之间的段里面。
当我们使用命令的时候,就根据命令的名字找到其对应的函数进行操作!