编译dts
你用的linux内核是什么版本?如果是3.0以上的版本,有arm/arm/boot/dts
❷ linux怎么调用dts生成dtb
dtb文件作用的描述是,使用dtb可以减少linux内核版本的数量。同一份linux 内核代码可以在多个板卡上运行,每个板卡可以使用自己的dtb文件。
1,在linux内核启动过程中会解析dtb文件,根据dtb文件中设备列表进行加注各个外设的驱动模块。
2,PC机在启动时会自动扫描外设,而在嵌入式中,linux内核启动过程中只是解析dtb文件,从而加载对应的模块。
3,编译linux内核时必须选择某外设模块,并且dtb中包括该外设的信息。在linux内核启动过程中才能自动加载该模块。
要使用dtb,需要uboot启动内核时,在bootm命令中指定dtb的位置,格式为:
bootm uImage_addr ramdisk_addr dtb_addr
如果没有ramdisk,就需要写成bootm uImage_addr - dtb_addr,用“-”表示没有ramdisk
❸ 编译linux内核设备树文件使用什么命令
Linux源码的arch/powerpc/boot/dts/目录下存放了很多dts文件,可以作为参考文件。另外dtc编译器在内核源码2.6.25版本之后已经被包含进去。在2.6.26版本之后,生成blob的简单规则已经加入makefile,如下命令:
$ make ARCH=powerpc canyonlands.dtb
也可以根据自己的硬件修改好dts文件后,用下面类似命令生成dtb文件。
$ dtc -f -I dts -O dtb -R 8 -S 0x3000 test.dts > mpc836x_mds.dtb
$ mkimage -A ppc -O Linux -T flat_dt -C none -a 0x300000 -e 0 -d mpc836x_mds.dtb mpc836x_mds.dtu
❹ 如何编译高通kernal设备树
DTS (device tree source)
.dts文件是一种ASCII 文本格式的Device
Tree描述,此文本格式非常人性化,适合人类的阅读习惯。基本上,在ARM
Linux在,一个。dts文件对应一个ARM的machine,一般放置在内核的arch/arm/boot/dts/目录。由于一个SoC可能对应多个machine(一个SoC可以对应多个产品和电路板),势必这些。dts文件需包含许多共同的部分,Linux内核为了简化,把SoC公用的部分或者多个machine共同的部分一般提炼为。dtsi,类似于C语言的头文件。其他的machine对应的。dts就include这个。dtsi。譬如,对于VEXPRESS而言,vexpress-v2m.dtsi就被vexpress-v2p-ca9.dts所引用,
vexpress-v2p-ca9.dts有如下一行:
/include/
“vexpress-v2m.dtsi”
当然,和C语言的头文件类似,。dtsi也可以include其他的。dtsi,譬如几乎所有的ARM
SoC的。dtsi都引用了skeleton.dtsi。
.dts(或者其include的。dtsi)基本元素即为前文所述的结点和属性:
[plain] view
plainprint?
/ {
node1 {
a-string-property = “A string”;
a-string-list-property = “first string”, “second string”;
a-byte-data-property = [0x01 0x23 0x34 0x56];
child-node1 {
first-child-property;
second-child-property = <1>;
a-string-property = “Hello, world”;
};
child-node2 {
};
};
node2 {
an-empty-property;
a-cell-property = <1 2 3 4>; /* each number (cell) is a uint32 */
child-node1 {
};
};
};
/ {
node1 {
a-string-property = “A string”;
a-string-list-property = “first string”, “second string”;
a-byte-data-property = [0x01 0x23 0x34 0x56];
child-node1 {
first-child-property;
second-child-property = <1>;
a-string-property = “Hello, world”;
};
child-node2 {
};
};
node2 {
an-empty-property;
a-cell-property = <1 2 3 4>; /* each number (cell) is a uint32 */
child-node1 {
};
};
};
上述。dts文件并没有什么真实的用途,但它基本表征了一个Device
Tree源文件的结构:
1个root结点“/”;
root结点下面含一系列子结点,本例中为“node1” 和
“node2”;
结点“node1”下又含有一系列子结点,本例中为“child-node1” 和
“child-node2”;
各结点都有一系列属性。这些属性可能为空,如“
an-empty-property”;可能为字符串,如“a-string-property”;可能为字符串数组,如“a-string-list-property”;可能为Cells(由u32整数组成),如“second-child-property”,可能为二进制数,如“a-byte-data-property”。
下面以一个最简单的machine为例来看如何写一个。dts文件。假设此machine的配置如下:
1个双核ARM
Cortex-A9 32位处理器;
ARM的local bus上的内存映射区域分布了2个串口(分别位于0x101F1000 和
0x101F2000)、GPIO控制器(位于0x101F3000)、SPI控制器(位于0x10170000)、中断控制器(位于0x10140000)和一个external
bus桥;
External bus桥上又连接了SMC SMC91111
Ethernet(位于0x10100000)、I2C控制器(位于0x10160000)、64MB NOR
Flash(位于0x30000000);
External bus桥上连接的I2C控制器所对应的I2C总线上又连接了Maxim
DS1338实时钟(I2C地址为0x58)。
其对应的。dts文件为:
[plain] view
plainprint?
/ {
compatible = “acme,coyotes-revenge”;
#address-cells = <1>;
#size-cells = <1>;
interrupt-parent = <&intc>;
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
compatible = “arm,cortex-a9”;
reg = <0>;
};
cpu@1 {
compatible = “arm,cortex-a9”;
reg = <1>;
};
};
serial@101f0000 {
compatible = “arm,pl011”;
reg = <0x101f0000 0x1000 >;
interrupts = < 1 0 >;
};
serial@101f2000 {
compatible = “arm,pl011”;
reg = <0x101f2000 0x1000 >;
interrupts = < 2 0 >;
};
gpio@101f3000 {
compatible = “arm,pl061”;
reg = <0x101f3000 0x1000
0x101f4000 0x0010>;
interrupts = < 3 0 >;
};
intc: interrupt-controller@10140000 {
compatible = “arm,pl190”;
reg = <0x10140000 0x1000 >;
interrupt-controller;
#interrupt-cells = <2>;
};
spi@10115000 {
compatible = “arm,pl022”;
reg = <0x10115000 0x1000 >;
interrupts = < 4 0 >;
};
external-bus {
#address-cells = <2>
#size-cells = <1>;
ranges = <0 0 0x10100000 0x10000 // Chipselect 1, Ethernet
1 0 0x10160000 0x10000 // Chipselect 2, i2c controller
2 0 0x30000000 0x1000000>; // Chipselect 3, NOR Flash
ethernet@0,0 {
compatible = “smc,smc91c111”;
reg = <0 0 0x1000>;
interrupts = < 5 2 >;
};
i2c@1,0 {
compatible = “acme,a1234-i2c-bus”;
#address-cells = <1>;
#size-cells = <0>;
reg = <1 0 0x1000>;
interrupts = < 6 2 >;
rtc@58 {
compatible = “maxim,ds1338”;
reg = <58>;
interrupts = < 7 3 >;
};
};
flash@2,0 {
compatible = “samsung,k8f1315ebm”, “cfi-flash”;
reg = <2 0 0x4000000>;
};
};
};
/ {
compatible = “acme,coyotes-revenge”;
#address-cells = <1>;
#size-cells = <1>;
interrupt-parent = <&intc>;
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
compatible = “arm,cortex-a9”;
reg = <0>;
};
cpu@1 {
compatible = “arm,cortex-a9”;
reg = <1>;
};
};
serial@101f0000 {
compatible = “arm,pl011”;
reg = <0x101f0000 0x1000 >;
interrupts = < 1 0 >;
};
serial@101f2000 {
compatible = “arm,pl011”;
reg = <0x101f2000 0x1000 >;
interrupts = < 2 0 >;
};
gpio@101f3000 {
compatible = “arm,pl061”;
reg = <0x101f3000 0x1000
0x101f4000 0x0010>;
interrupts = < 3 0 >;
};
intc: interrupt-controller@10140000 {
compatible = “arm,pl190”;
reg = <0x10140000 0x1000 >;
interrupt-controller;
#interrupt-cells = <2>;
};
spi@10115000 {
compatible = “arm,pl022”;
reg = <0x10115000 0x1000 >;
interrupts = < 4 0 >;
};
external-bus {
#address-cells = <2>
#size-cells = <1>;
ranges = <0 0 0x10100000 0x10000 // Chipselect 1, Ethernet
1 0 0x10160000 0x10000 // Chipselect 2, i2c controller
2 0 0x30000000 0x1000000>; // Chipselect 3, NOR Flash
ethernet@0,0 {
compatible = “smc,smc91c111”;
reg = <0 0 0x1000>;
interrupts = < 5 2 >;
};
i2c@1,0 {
compatible = “acme,a1234-i2c-bus”;
#address-cells = <1>;
#size-cells = <0>;
reg = <1 0 0x1000>;
interrupts = < 6 2 >;
rtc@58 {
compatible = “maxim,ds1338”;
reg = <58>;
interrupts = < 7 3 >;
};
};
flash@2,0 {
compatible = “samsung,k8f1315ebm”, “cfi-flash”;
reg = <2 0 0x4000000>;
};
};
};
上述。dts文件中,root结点“/”的compatible 属性compatible =
“acme,coyotes-revenge”;定义了系统的名称,它的组织形式为:<manufacturer>,<model>。Linux内核透过root结点“/”的compatible
属性即可判断它启动的是什么machine。
在。dts文件的每个设备,都有一个compatible
属性,compatible属性用户驱动和设备的绑定。compatible
属性是一个字符串的列表,列表中的第一个字符串表征了结点代表的确切设备,形式为“<manufacturer>,<model>”,其后的字符串表征可兼容的其他设备。可以说前面的是特指,后面的则涵盖更广的范围。如在arch/arm/boot/dts/vexpress-v2m.dtsi中的Flash结点:
[plain] view
plainprint?
flash@0,00000000 {
compatible = “arm,vexpress-flash”, “cfi-flash”;
reg = <0 0x00000000 0x04000000>,
<1 0x00000000 0x04000000>;
bank-width = <4>;
};
flash@0,00000000 {
compatible = “arm,vexpress-flash”, “cfi-flash”;
reg = <0 0x00000000 0x04000000>,
<1 0x00000000 0x04000000>;
bank-width = <4>;
};
compatible属性的第2个字符串“cfi-flash”明显比第1个字符串“arm,vexpress-flash”涵盖的范围更广。
再比如,Freescale
MPC8349 SoC含一个串口设备,它实现了国家半导体(National Semiconctor)的ns16550
寄存器接口。则MPC8349串口设备的compatible属性为compatible = “fsl,mpc8349-uart”,
“ns16550”。其中,fsl,mpc8349-uart指代了确切的设备, ns16550代表该设备与National Semiconctor
的16550
UART保持了寄存器兼容。
接下来root结点“/”的cpus子结点下面又包含2个cpu子结点,描述了此machine上的2个CPU,并且二者的compatible
属性为“arm,cortex-a9”。
注意cpus和cpus的2个cpu子结点的命名,它们遵循的组织形式为:<name>[@<unit-address>],<>中的内容是必选项,[]中的则为可选项。name是一个ASCII字符串,用于描述结点对应的设备类型,如3com
Ethernet适配器对应的结点name宜为ethernet,而不是3com509。如果一个结点描述的设备有地址,则应该给出@unit-address。多个相同类型设备结点的name可以一样,只要unit-address不同即可,如本例中含有cpu@0、cpu@1以及serial@101f0000与serial@101f2000这样的同名结点。设备的unit-address地址也经常在其对应结点的reg属性中给出。ePAPR标准给出了结点命名的规范。
❺ 嵌入式linux 修改dts文件同时需要修改preloader么
U-Boot 引入了扁平设备树FDT 这样的动态接口,使用一个单独的FDT blob(二进制大对象,是一个可以存储二进制文件的容器)存储传递给内核的参数[3]。一些确定信息,例如cache 大小、中断路由等直接由设备树提供,而其他的信息,例如eTSEC 的MAC 地址、频率、PCI 总线数目等由U-Boot 在运行时修改。U-Boot 使用扁平设备树取代了bd_t,而且也不再保证对bd_t 的后向兼容。需要修改的,重新编译dts文件。
❻ linux编译u-boot时显示[arch/arm/dts/zynq-zc702.dtb]错误
在编译uboot的时候,会出现出错,因此我们要首先做 make disclean. 将原来的一些中间文件清理干净。
因此在编译Uboot依次执行 1.make disclean
2.make smdk2440_config
3. make
就可以编译通过了
❼ odt在dts设置
在源码中直接修改board.dts文件->重新编译&打包->烧写到设备里。
在设备BSP调试的过程中,经常会出现需要修改DTS的情况,比如调试一个新的屏幕、传感器或者wifi模组,传统的方法是:在源码中直接修改board.dts文件->重新编译&打包->烧写到设备里这种方法繁杂,编译和烧写都要花费时间,严重影响开发效率。
因此,全志(其实是uboot提供的)提供了一个启动阶段DTS调试的方法,可以让我们在启动阶段就把DTS改掉,这次启动加载的就是改后的DTS。*注:这种修改是一次性的,不可以保存的,只限这次启动的时候生效,断电或者重启就不生效了1.设备上电过程中串口按住电脑键盘的"s"按键,让设备进入boot:*注:是真的按住调试的电脑的键盘的s按键,和按住2另设备跳烧录的操作一样。如果进入boot成功,就会有如下log,这时就可以在串口对设备进行DTS修改操作。
❽ Ubuntu编译u-boot时显示[arch/arm/dts/zynq-zc702.dtb]错误
最好贴上完整的log,这样才知道整个状况。
❾ 如何将dtb反编译成dts
由于device tree会将一个node的信息分布在各个文件里,查看起来很不方便,比如如下例子,ldb在三个文件中都有配置:
imx6qdl-sabresd.dtsi:
&ldb {
status = "okay";
.......
};
imx6qdl.dtsi:
ldb: ldb@020e0008 {
#address-cells = <1>;
#size-cells = <0>;
......
};
imx6q.dtsi:
&ldb {
compatible = "fsl,imx6q-ldb", "fsl,imx53-ldb";
.......
}
其实device tree编译之后最终是会被全部放在一个.dtb结尾的文件,
比如这里是imx6q-sabresd-ldo.dtb,用如下命令就可以看到整个ldb node的内容,而且也可以作为编译之后的检查。
[kris@ecovacs:~/kernel_imx/scripts/dtc]$
./dtc -I dtb -O dts ../../arch/arm/boot/dts/imx6q-sabresd-ldo.dtb > ~/f.dts
❿ linux加载dts的时候会创建设备节点吗
From:http://m.blog.csdn.net/blog/liliyaya/9188193
1. 在\kernel\of\fdt.c 中有如下初始化函数 注释上:展开设备树,创建device_nodes到全局变量allnodes中
void __init unflatten_device_tree(void)
{
__unflatten_device_tree(initial_boot_params, &allnodes,
early_init_dt_alloc_memory_arch);
/* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */
of_alias_scan(early_init_dt_alloc_memory_arch);
}
unflatten_device_tree函数被setup_arch函数调用,
因为我们使用得是arm平台所以存在\kernel\arch\arm\kernel\setup.c中
void __init setup_arch(char **cmdline_p)
{
unflatten_device_tree()
}
setup_arch函数在kernel启动是被调用,如下启动kernel存在\kernel\init\main.c中
asmlinkage void __init start_kernel(void)
{
setup_arch(&command_line);
}
这些工作完成解析DTS文件。保存到全局链表allnodes中。
2、在makefile中有这段话来编译dts文件:
$(obj)/A20%.dtb: $(src)/dts/A20%.dts FORCE
$(call if_changed_dep,dtc)
$(obj)/A68M%.dtb: $(src)/dts/A68M%.dts FORCE
$(call if_changed_dep,dtc)
和.c文件生成.o文件一样 回生成.dtb文件。在
/home/liyang/workspace/SZ_JB-mr1-8628-bsp-1012/out/target/proct/msm8226/obj/KERNEL_OBJ/arch/arm/boot
目录下,与zimage一个目录。
3、
在 board-8226.c中有初始化函数-->启动自动掉用
void __init msm8226_init(void)
{
of_platform_populate(NULL, of_default_bus_match_table, adata, NULL);
}
of_platform_populate在kernel\driver\of\platform.c中定义,回查询
root = root ? of_node_get(root) : of_find_node_by_path("/");
for_each_child_of_node(root, child)
{
rc = of_platform_bus_create(child, matches, lookup, parent, true);
if (rc)
break;
}
of_node_put(root);
在这里用到得函数of_find_node_by_path会最终调用到kernel\driver\of\base.c中得函数
struct device_node *of_find_node_by_path(const char *path)
{
遍历第1步中得allnodes找到根节点
}
of_platform_bus_create()函数中创建得内容存在了 adata中。
以下内容为转载:
(2)使用DTS注册总线设备的过程
以高通8974平台为例,在注册i2c总线时,会调用到qup_i2c_probe()接口,该接口用于申请总线资源和添加i2c适配器。在成功添加i2c适配器后,会调用of_i2c_register_devices()接口。此接口会解析i2c总线节点的子节点(挂载在该总线上的i2c设备节点),获取i2c设备的地址、中断号等硬件信息。然后调用request_mole()加载设备对应的驱动文件,调用i2c_new_device(),生成i2c设备。此时设备和驱动都已加载,于是drvier里面的probe方法将被调用。后面流程就和之前一样了。
简而言之,Linux采用DTS描述设备硬件信息后,省去了大量板文件垃圾信息。Linux在开机启动阶段,会解析DTS文件,保存到全局链表allnodes中,在掉用.init_machine时,会跟据allnodes中的信息注册平台总线和设备。值得注意的是,加载流程并不是按找从树根到树叶的方式递归注册,而是只注册根节点下的第一级子节点,第二级及之后的子节点暂不注册。Linux系统下的设备大多都是挂载在平台总线下的,因此在平台总线被注册后,会根据allnodes节点的树结构,去寻找该总线的子节点,所有的子节点将被作为设备注册到该总线上。