linux u-boot对设备树的支持

一、传递dtb给内核 : r2

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时对应参数写为"-"

2、bootm命令怎么把dtb_addr写入r2寄存器传给内核?

ARM程序调用规则(ATPCS)
c_function(p0, p1, p2) // p0 => r0, p1 => r1, p2 => r2
定义函数指针 the_kernel, 指向内核的启动地址,
//machine_id设备ID,0x32000000S设备树地址
然后执行: the_kernel(0, machine_id, 0x32000000);

3、 dtb_addr 的选择

c.1 不要破坏u-boot本身
c.2 不要挡内核的路: 内核本身的空间不能占用, 内核要用到的内存区域,也不能占用内核启动时一般会在它所处位置的下边放置页表, 这块空间(一般是0x4000即16K字节)不能被占用

4、内存使用分布图

JZ2440内存使用情况:
------------------------------
0x33f80000 ->| u-boot |
------------------------------
| u-boot所使用的内存(栈等)|
------------------------------
| |
| |
| 空闲区域 |
| |
| |
| |
| |
------------------------------
0x30008000 ->| zImage |
------------------------------ uImage = 64字节的头部+zImage
0x30007FC0 ->| uImage头部 |
------------------------------
0x30004000 ->| 内核创建的页表 | head.S
------------------------------
| |
| |
-----> ------------------------------
|
|
— (内存基址 0x30000000)

5、查看uImage在内存的存放位置

在这里插入图片描述

6、错误的实例

命令示例:
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

二、dtb的修改原理

1、修改新的dts属性的值

在这里插入图片描述

2、添加一个新的属性

在这里插入图片描述

3、新uboot支持了对dts的操作

fdt命令调用过程:
fdt set []
a. 根据path找到节点
b. 根据val确定新值长度newlen, 并把val转换为字节流
c. fdt_setprop
c.1 fdt_setprop_placeholder // 为新值在DTB中腾出位置
fdt_get_property_w // 得到老值的长度 oldlen
fdt_splice_struct_ // 腾空间
fdt_splice_ // 使用memmove移动DTB数据, 移动(newlen-oldlen)
fdt_set_size_dt_struct // 修改DTB头部, size_dt_struct
fdt_set_off_dt_strings // 修改DTB头部, off_dt_strings
c.2 memcpy(prop_data, val, len); // 在DTB中存入新值

猜你喜欢

转载自blog.csdn.net/qq_18077275/article/details/108857795