dtb编译与解析

一、前言

dtb是dts文件编译后的二进制文件。dts文件能够重写节点的配置,也可在当前节点中引用其它节点。这种特性使得dts的不同节点直接可以进行配置的继承和重写,在大量重复配置、固定配置的场景下比json、xml等更适合作为配置文件。本文将基于如何将dts作为一种易于解析的配置文件展开讨论,而不是作为内核设备描述的设备树。

二、DTS的基本语法

此处将的基础语法并不是dts属性、值怎么写。而是基础的框架保证编译通过,其它语法可以在网上轻松百度到。

1) 版本号声明

1
/dts-v1/;

在dts中需要添加版本号声明,否则编译会报错:

1
2
Error: a.dts:3.1-2 syntax error
FATAL ERROR: Unable to parse input tree

2) 如何包含其它dts

1
/include/ "xx.dtsi"

dts只支持使用这种方式进行头文件包含,但是我们往往会见到#include "xxx.dtsi"格式的文件包含,在第二章第二小节宏定义与预处理会详细说明。

二、如何编译DTS

1) 简单编译

使用dtc命令就可以编译dts设备树文件。

a.dts

1
2
3
4
5
6
7
/dts-v1/;
/ {
test {
count = <8>;
size = <128>;
};
};
1
2
3
4
5
# 编译设备树
# -I:指定输入格式
# -O:指定输出格式
# -o:指定输出文件
dtc -I dts -O dtb -o a.dtb a.dts

通过上述命令可以编译出对应的dtb文件

2) 宏定义与预处理

dtc命令本身不支持预处理指令,直接在dts中写#include "xxx.dtsi"在编译时会报语法错,但是我们依然可以在很多设备树中看到include及其它各种预处理指令。要实现这种效果可以使用gcc先对文件进行预处理,再使用dtc命令进行编译。

a.dts

1
2
3
4
5
6
7
/dts-v1/;
/ {
test:test {
count = <8>;
size = <128>;
};
};

b.dts

1
2
3
4
5
#include "a.dts"
&test {
size = <256>;
string = "hello";
};

此时需要使用以下命令进行编译

1
2
3
4
5
6
# $CC 代表gcc编译器(理论上使用任何平台的都不影响,此处仅进行预处理)
# -x assembler-with-cpp:指定预处理语法(包括#号开头的各种宏命令,以及注释),若使用c则会对#address 等报错
# -E:仅进行预处理,不编译
# -P:不输出#号开头的一些信息
# -o:指定输出文件
$CC -x assembler-with-cpp -E -P b.dts -o .b.dts.tmp

经过上述的预处理,.b.dts.tmp的内容如下:

.b.dts.tmp

1
2
3
4
5
6
7
8
9
10
11
/dts-v1/;
/ {
test:test {
count = <8>;
size = <128>;
};
};
&test {
size = <256>;
string = "hello";
};

再重新编译.b.dts.tmp文件即可

0%