一.u-boot启动内核的流程:
1.从NAND/NOR中将内核读取到内存
2.设置TAG参数
3.跳转执行内核:thekernel(0,机器ID,参数存放地址)
二.内核的启动流程
1. 根据R1,判断能否支持该单板,如果能够支持调用机器相关的初始化函数,否则卡死
2. 解析TAG参数
3. 装载驱动程序(flash、网卡)
4. 挂接根文件系统
5. 启动应用程序
三.内核启动流程,据此配置内核(机器ID)
1.修改Makefile
ARCH ?= arm//架构
CROSS_COMPILE ?= arm-linux-//交叉编译工具链
2.使用默认配置
Make s3c2410_defconfig
3.Make uImage
u-boot的默认机器ID为MACH_TYPE_SMDK2410
四.修改
1.Make uImage一次编译成功,编译成功后用nfs命令下载:
Nfs 32000000 192.168.1.19:/work/nfs_root/uImage_new//这个命令的意思是用nfs命令,从服务器指定文件夹将uImage下载到32000000地址
Bootm 32000000
2.分析u-boot中启动内核的源码:cmd_bootm.c
(1)U_BOOT_CMD(
bootm,CONFIG_SYS_MAXARGS,1,do_bootm,//调用do_bootm函数
"boot application image from memory",
"[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"
(2)u-boot跳转执行内核
static void boot_jump_linux(bootm_headers_t *images)//(bootm.c)
在这个函数中如果通过设置了machid即s = getenv("machid");则使用这个设置的id,否则使用默认的机器id,gd->bd->bi_arch_number=MACH_TYPE_SMDK2410
这个机器id必须为内核所支持的机器id
(3)在Linux内核中根据u-boot传递的机器id,找到该款单板的初始化函数
如何确定内核支持哪些单板?
Cd arch/arm/mach*.c
机器ID的作用
例如:设置的机器ID是16a,则会根据这个数值在
arch/arm/mach-s3c24xx/mach-smdk2440.c
中找到MACHINE_START(S3C2440,”SMDK2440”)结构体,调用其中的初始化函数
MACHINE_START(S3C2440, "SMDK2440")
/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
.atag_offset= 0x100,
.init_irq= s3c24xx_init_irq,
.map_io= smdk2440_map_io,
.init_machine= smdk2440_machine_init,
.timer= &s3c24xx_timer,
.restart= s3c244x_restart,
MACHINE_END
这个结构体可以展开:
Static const struct machine_desc __mach_desc_s3c2440
__used
__attribute__((__section__(“.arch.info.init”)))={
.nr=MACH_TYPE_S3C2440,
.name=”SMDK2440”,
...
};
五.遇到的问题
1.使用7cf的机器ID时,串口能够有正确的输出信息,使用16a的机器ID时,串口出现乱码
修改:在arch/arm/mach-s3c24xx/mach-smdk2440.c中有一个函数:
S3c24xx_init_clocks(12000000);//这个函数是设置晶振频率,由于单板使用的是12MHZ 晶振,所以必须将数值设置为12000000