作者:彭東林
1、如何查看編譯生成的設備樹的內容?
在設備樹學習的時候,如果可以看到最終生成的設備樹的內容,對於我們學習設備樹以及分析問題有很大幫助。這裏我們需要使用設備樹生成工具dtc的反編譯功能
root@pengdl-VirtualBox:~/tq2440/Linux/linux-4.0.1# ./scripts/dtc/dtc -h
Usage: dtc [options] <input file>
Options: -[qI:O⭕️V:d:R:S:p:fb:i:H:sW:E:hv]
-q, –quiet
Quiet: -q suppress warnings, -qq errors, -qqq all
-I, –in-format <arg>
Input formats are:
dts - device tree source text
dtb - device tree blob
fs - /proc/device-tree style directory
-o, --out <arg>
Output file
-O, --out-format <arg>
Output formats are:
dts - device tree source text
dtb - device tree blob
asm - assembler source
-V, --out-version <arg>
Blob version to produce, defaults to %d (for dtb and asm output)
-d, --out-dependency <arg>
Output dependency file
-R, --reserve <arg>
tMake space for <number> reserve map entries (for dtb and asm output)
-S, --space <arg>
Make the blob at least <bytes> long (extra space)
-p, --pad <arg>
Add padding to the blob of <bytes> long (extra space)
-b, --boot-cpu <arg>
Set the physical boot cpu
-f, –force
Try to produce output even if the input tree has errors
-i, --include <arg>
Add a path to search for include files
-s, –sort
Sort nodes and properties before outputting (useful for comparing trees)
-H, --phandle <arg>
Valid phandle formats are:
legacy - “linux,phandle” properties only
epapr - “phandle” properties only
both - Both “linux,phandle” and “phandle” properties
-W, --warning <arg>
Enable/disable warnings (prefix with “no-”)
-E, --error <arg>
Enable/disable errors (prefix with “no-”)
-h, –help
Print this help and exit
-v, –version
Print version and exit
假設我們最終的設備樹文件是:arch/arm/boot/dts/s3c2416-smdk2416.dtb
./scripts/dtc/dtc -I dtb -O dts -o output.dts arch/arm/boot/dts/s3c2416-smdk2416.dtb
輸出文件output.dts就是反彙編的結果,他就是實際生成的設備樹,當然也可以重新將生成的dts文件在編譯成dtb文件:
./scripts/dtc/dtc -I dts -O dtb -o s3c2416-smdk2416.dtb output.dts
2、分析工具fdtdump
在Linux的scripts/dtc目錄下除了提供dtc工具外,還提供了一個叫做fdtdump的工具,對於分析設備樹也非常有幫助。
用法:
fdtdump -h
Usage: fdtdump [options] <file>
Options: -[dshV]
-d, --debug Dump debug information while decoding the file
-s, --scan Scan for an embedded fdt in file
-h, –help Print this help and exit
-V, --version Print version and exit
使用範例:
fdtdump -sd vexpress-v2p-ca9.dtb | tee vexpress.dts.debug
看看輸出的文件:
vexpress-v2p-ca9.dtb: found fdt at offset 0
/dts-v1/;
// magic: 0xd00dfeed
// totalsize: 0x2e9c (11932)
// off_dt_struct: 0x38
// off_dt_strings: 0x2bb8
// off_mem_rsvmap: 0x28
// version: 17
// last_comp_version: 16
// boot_cpuid_phys: 0x0
// size_dt_strings: 0x2e4
// size_dt_struct: 0x2b80
// 0038: tag: 0x00000001 (FDT_BEGIN_NODE)
/ {
// 0040: tag: 0x00000003 (FDT_PROP)
// 2bb8: string: model
// 004c: value
model = “V2P-CA9”;
可以看到,其中這個工具會同時把分析語句和原始文件打印出來,其中 // 後輸出的是分析語句,其他的是原始語句。對分析Linux內核啓動時遍歷展開設備樹鏡像很有幫助。
3、Linux配置,支持設備樹
make menuconfig ---> Boot options ---> Flattened Device Tree support
4、Linux 編譯設備樹
可以看看arch/arm/boot/dts/Makefile中你要的那個設備樹的dtb文件是否配置上了。
make dtbs
5、從Linux內核代碼中編譯設備樹的工具dtc
在內核源碼目錄下提供了dtc工具的源碼實現, 下面是生成這個工具的命令:
make scripts
6、刪除設備樹屬性的方法
有時我們有這樣的需求,需要刪除設備樹的某些屬性, 但是我們又不想修改設備樹源文件,那麼可以利用delete-property方法。
1 / {
2 ... ...
3 demo1: demo1 {
4 compatible = "demo1";
5 property1 = <1>;
6 property2;
7 property3 = <2>;
8 property4;
9 };
10 };
11
12 &demo1 {
13 /delete-property/property2;
14 /delete-property/property3;
15 };
編譯完成後,執行反編譯可以看到property2和property3已經消失了:
1 demo1 {
2 compatible = "demo1";
3 property1 = <0x1>;
4 property4;
5 };
7、兩個內核新增的設備樹調試工具(強烈推薦)
- ./scripts/dtc/dt_to_config
可以根據傳入的設備樹解析出每個節點對應那些驅動以及內核是否已經配置,甚至可以通過傳遞--config-format來直接修改.config文件,如果嫌節點的路徑過長,可以傳遞參數--short-name,用法示例:
# 這裏的--include-suspec用於解析設備樹中的include字段
$./scripts/dtc/dt_to_config arch/arm/boot/dts/s3c2440-tq2440-dt.dts --include-suspect --config ./.config
-dDc-E-Hx---- : /i2c-gpio-1 : i2c-gpio : arch/arm/mach-ep93xx/core.c : obj-y : x
-dDc-E-H-n--F : /i2c-gpio-1 : i2c-gpio : arch/arm/mach-ixp4xx/avila-setup.c : CONFIG_MACH_AVILA : n
-dDc-E-H-n--F : /i2c-gpio-1 : i2c-gpio : arch/arm/mach-ixp4xx/dsmg600-setup.c : CONFIG_MACH_DSMG600 : n
...
當然後面也可以直接跟dtb文件:
$./scripts/dtc/dt_to_config arch/arm/boot/dts/s3c2440-tq2440-dt.dtb --include-suspect --config ./.config
-dDc-E-Hx---- : /i2c-gpio-1 : i2c-gpio : arch/arm/mach-ep93xx/core.c : obj-y : x
-dDc-E-H-n--F : /i2c-gpio-1 : i2c-gpio : arch/arm/mach-ixp4xx/avila-setup.c : CONFIG_MACH_AVILA : n
-dDc-E-H-n--F : /i2c-gpio-1 : i2c-gpio : arch/arm/mach-ixp4xx/dsmg600-setup.c : CONFIG_MACH_DSMG600 : n
-dDc-E-H-n--F : /i2c-gpio-1 : i2c-gpio : arch/arm/mach-ixp4xx/fsg-setup.c : CONFIG_MACH_FSG : n
...
- ./scripts/dtc/dtx_diff
這個工具用於比較兩個設備樹,也可以對設備樹反編譯。示例:
#傳遞一個設備樹,表示反編譯
./scripts/dtc/dtx_diff arch/arm/boot/dts/s3c2440-tq2440-dt.dtb
#也可以直接傳遞一個dts文件,這個工具會將該dts文件展開
./scripts/dtc/dtx_diff arch/arm/boot/dts/s3c2440-tq2440-dt.dts
#傳遞兩個設備樹表示比較
./scripts/dtc/dtx_diff arch/arm/boot/dts/s3c2440-tq2440-dt.dtb /tftpboot/dtb
— /dev/fd/63 2017-09-23 22:01:48.407691984 +0800
+++ /dev/fd/62 2017-09-23 22:01:48.407691984 +0800
@@ -125,7 +125,7 @@
pinctrl-names = “default”;
reg = <0x54000000 0x100>;
samsung,i2c-max-bus-freq = <0x30d40>;
- status = “disabled”;
+ status = “okay”;
demo0@</span><span style="color: #800080;">51</span><span style="color: #000000;"> {
compatible </span>= <span style="color: #800000;">"</span><span style="color: #800000;">demo0</span><span style="color: #800000;">"</span>;</span></pre>
也可以都是dts文件,或者一個dts一個dtb文件。
8、如何在設備樹裏控制屬性值佔用的字節數?
9、設備樹中ranges屬性分析(1)
其他關於設備樹的調試文檔
2、Youtube:Solving Devicetree Issues, part 3.0
3、Linux kernel的devicetree-compiler郵件列表裏有很多好的patch,可以挑選自己想要的, 比如下面幾個:
[RFC PATCH 0/3] dtc: dts source location annotation 這個系列的patch爲dtc增加了一個annotate配置,這樣在編譯設備樹時會生成annotate.dts.tmp後綴的隱藏文件,可以查看每個屬性最終是被那個設備樹文件設置的
[RFC PATCH 1/3] dtc: dts source location annotation
[RFC PATCH 2/3] dtc: make check test for dtc --annotate
[RFC PATCH 3/3] dtc: linux kernel build process to create annotated .dts
效果:
sdhci@f9824900 { /* arch/arm/boot/dts/qcom-apq8074-dragonboard.dts:14 */ compatible = "qcom,sdhci-msm-v4"; /* arch/arm/boot/dts/qcom-msm8974.dtsi:240 */ reg = <0xf9824900 0x11c 0xf9824000 0x800>; /* arch/arm/boot/dts/qcom-msm8974.dtsi:241 */ reg-names = "hc_mem", "core_mem"; /* arch/arm/boot/dts/qcom-msm8974.dtsi:242 */ interrupts = <0x0 0x7b 0x0 0x0 0x8a 0x0>; /* arch/arm/boot/dts/qcom-msm8974.dtsi:243 */ interrupt-names = "hc_irq", "pwr_irq"; /* arch/arm/boot/dts/qcom-msm8974.dtsi:244 */ clocks = <0xd 0xd8 0xd 0xd7>; /* arch/arm/boot/dts/qcom-msm8974.dtsi:245 */ clock-names = "core", "iface"; /* arch/arm/boot/dts/qcom-msm8974.dtsi:246 */ status = "ok"; /* arch/arm/boot/dts/qcom-apq8074-dragonboard.dts:17 */ bus-width = <0x8>; /* arch/arm/boot/dts/qcom-apq8074-dragonboard.dts:15 */ non-removable; /* arch/arm/boot/dts/qcom-apq8074-dragonboard.dts:16 */ }; /* arch/arm/boot/dts/qcom-apq8074-dragonboard.dts:18 */