在线课堂:https://www.100ask.net/index(课程观看)
论 坛:http://bbs.100ask.net/(学术答疑)
开 发 板:https://100ask.taobao.com/ (淘宝)
https://weidongshan.tmall.com/(天猫)
交流群一:QQ群:869222007(鸿蒙开发/Linux/嵌入式/驱动/资料下载)
交流群二:QQ群:536785813(单片机-嵌入式)
公 众 号:百问科技
前言:
本文转自韦东山老师的相关文章,原文链接:第四课:u-boot对设备树的支持
一、传递 dtb 给内核
先把设备树文件读到内存,在启动内核时把设备树的地址写到 R2 寄存器中。
1.1、u-boot 中内核启动命令:
bootm <uImage_addr> // 无设备树,bootm 0x30007FC0
bootm <uImage_addr> <initrd_addr> <dtb_addr> // 有设备树
比如:
nand read.jffs2 0x30007FC0 kernel; // 读内核uImage到内存0x30007FC0
nand read.jffs2 32000000 device_tree; // 读dtb到内存32000000
bootm 0x30007FC0 - 0x32000000 // 启动, 没有initrd时对应参数写为"-"
1.2、bootm 命令怎么把 dtb_addr 写入 R2 寄存器传给内核?
在百度搜索 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.3、dtb_addr 可以随便选吗?
- 不要破坏 u-boot 本身;
- 不要挡内核的路:内核本身的空间不能占用,内核要用到的内存区域也不能占用;
内核启动时一般会在它所处位置的下边防止页表,这块空间(一般是 0x400 即 16K 字节)不能被占用。
------------------------------
0x33f80000 ->| u-boot | 分析lds链接文件
------------------------------
| u-boot所使用的内存(栈等)|
------------------------------
| |
| |
| 空闲区域 |
| |
| |
| |
| |
------------------------------
0x30008000 ->| zImage |
------------------------------ uImage = 64字节的头部+zImage
0x30007FC0 ->| uImage头部 |
------------------------------
0x30004000 ->| 内核创建的页表 | head.S
------------------------------
| |
| |
-----> ------------------------------
|
|
--- (内存基址 0x30000000)
我如何知道内核放在 0x30008000?
在内核目录下执行 mkimage -l arch/arm/boot/uImage
命令示例:
a、可以启动:
nand read.jffs2 30000000 device_tree
nand read.jffs2 0x30007FC0 kernel
bootm 0x30007FC0 - 30000000
b、不可以启动:内核启动时会使用 0x30004000 的内存来存放页表,dtb 会被破坏
nand read.jffs2 30004000 device_tree
nand read.jffs2 0x30007FC0 kernel
bootm 0x30007FC0 - 30004000