在之前的文章中介绍过在启动内核时把设备树的地址写到r2寄存器中,并且设备数在内存中的储存信息空间被保留,有无设备树u-boot启动内核的命令是不同的:
bootm <uImage_addr> // 无设备树
bootm <uImage_addr> <initrd_addr> <dtb_addr> // 有设备树
例如:
bootcmd=nand read.jffs2 0x30007FC0 kernel; nand read.jffs2 32000000 device_tree; bootm 0x30007FC0 - 0x32000000
nand read.jffs2 0x30007FC0 kernel; // 读内核uImage到内存0x30007FC0
nand read.jffs2 32000000 device_tree; // 读dtb到内存32000000
bootm 0x30007FC0 - 0x32000000 // 启动, 没有initrd时对应参数写为"-"
对于uboot怎样把设备树的地址传给linux内核,我会在后面的文章中详细的介绍,在这里我只是简单的介绍,在百度搜索ARM程序调用规则(ATPCS) 写一个c函数
c_function(p0, p1, p2) // p0 => r0, p1 => r1, p2 => r2(3个参数分别保存到相应的寄存器)
定义函数指针 the_kernel, 指向内核的启动地址,然后执行: the_kernel(0, machine_id, 0x32000000);
armlinux.c中
/* 100ask for device tree, no initrd image used */
if (argc == 4) {
//第三个参数0x32000000就是设备树地址
of_flat_tree = (char *) simple_strtoul(argv[3], NULL, 16);
if (be32_to_cpu(*(ulong *)of_flat_tree) == OF_DT_HEADER) {
printf ("\nStarting kernel with device tree at 0x%x...\n\n", of_flat_tree);
cleanup_before_linux ();
//把dtb的地址传到r2寄存器里
theKernel (0, bd->bi_arch_number, of_flat_tree);
} else {
printf("Bad magic of device tree at 0x%x!\n\n", of_flat_tree);
}
}
- 虽然设备树在内存中的空间是被保留的,但是在内存中的存储地址空间不是随便选的,选择设备树在内存中的存储地址需要考虑两个因素:
1、不要破坏u-boot本身; 2、不要挡内核的路: 内核本身的空间不能占用, 内核要用到的内存区域也不能占用 内核启动时一般会在它所处位置的下边放置页表, 这块空间(一般是0x4000即16K字节)不能被占用
ARM内存使用框图:
------------------------------
0x33f80000 ->| u-boot | 分析lds链接文件
------------------------------
| u-boot所使用的内存(栈等)|
------------------------------
| |
| |
| 空闲区域 |
| |
| |
| |
| |
------------------------------
0x30008000 ->| zImage |
------------------------------ uImage = 64字节的头部+zImage
0x30007FC0 ->| uImage头部 |
------------------------------
0x30004000 ->| 内核创建的页表 | head.S
------------------------------
| |
| |
-----> ------------------------------
|
|
--- (内存基址 0x30000000)
- 我如何知道内核放在 0x30008000 在内核目录下执行
mkimage -l arch/arm/boot/uImage
里面显示内核的load address = 0x30008000 最终运行也在0x30008000位置命令示例:
1.、可以启动:
nand read.jffs2 30000000 device_tree
nand read.jffs2 0x30007FC0 kernel
bootm 0x30007FC0 - 30000000
2、 不可以启动: 内核启动时会使用0x30004000的内存来存放页表,dtb会被破坏
nand read.jffs2 30004000 device_tree
nand read.jffs2 0x30007FC0 kernel
bootm 0x30007FC0 - 30004000