1、dts文件在哪里
(1)早期版本的硬件信息 .h 文件多放在arch/arm/mach-xxx 或者arch/arm/plat-xxx中
新版本内核使用了设备树却还保留这些文件,是为了向前兼容,使之前未用设备树的芯片也可以使用该版本内核。
(2)dts文件放在arch/arm/boot/dts目录中
本专栏文章是基于HI3516DV300平台进行学习的,所以我们关注的设备树文件是图中用红色标记出的那两个。
hi3516dv300-demb.dts:demb表示是官方开发板(华为海思),我们专栏学习使用的开发板
和官方开发板相似度很高,所以可以直接使用官方开发板的文件
hi3516dv300.dtsi
2、dts的格式简介
(1)后缀名一般为dts和dtsi,可以被include,甚至可以include那些C语言的头文件,dtsi文件可以理解为dts的头文件,dtsi的 i 就是include,其在dts文件中被include包含。
(2)dtsi一般写soc共性部分,而dts一般写目标单板特性部分,所以一般dts包含并重写部分dtsi
(3)注释用/* */,注意#开头的不是注释
(4)分号是段落块之间的分隔符,{}和[]和<>是段落块的封装符号,和C语言语言类似
(5)/dts-v1/节点,表示dts的版本号,目前都是v1
(6)/{}是根节点root node,理论上只应该有一个根节点,有说法dtc会合并所有root node为同一个(源文件看起来是有多个根节点的),根节点的名称必须是"/"
(7)dts是树状的多节点组织,基本单元是node,除root外其他node都有parent,还可以有child
3、dts的节点格式
(1)格式定义
[label:] <node-name> [@<unit-address>]{
[property]
[child nodes]
[child nodes]
......
};
label:表示节点的一个别名,可以有也可以无,类似一个符号链接
node-name:表示节点的正式名称
@<unit-address>:单元地址,即这个node对应的地址,如同串口有很多个寄存器,这个地址表示寄存器的基地址,因为串口的寄存器地址是连续排列的
property:属性,节点的属性,使用“ = ”
child nodes:子节点
(2)格式解读
[]:表示该项可以省略,<>表示不可省略
[label]:标签,为了方便访问节点,后面可以直接通过&label来访问该节点。
node-name:节点名称。根节点的名称必须是/
[@unit-address]:地址,如cpu node就是0、1这种,reg node就是0x12010000这种
(3)实战演练,分析阅读3516dv300的dts
/*
* Copyright (c) 2013-2014 Linaro Ltd.
* Copyright (c) 2015-2017 HiSilicon Technologies Co., Ltd.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/dts-v1/;
#include "hi3516dv300.dtsi"
/ {
model = "Hisilicon HI3516DV300 DEMO Board";
compatible = "hisilicon,hi3516dv300";
memory {
device_type = "memory";
reg = <0x82000000 0x20000000>;
};
};
&uart0 {
status = "okay";
};
&uart1 {
status = "okay";
};
&uart4 {
status = "okay";
};
#ifndef CONFIG_ARCH_HISI_BVT_AMP
&i2c_bus0 {
status = "okay";
clock-frequency = <100000>;
};
&i2c_bus1 {
status = "okay";
clock-frequency = <100000>;
};
&i2c_bus2 {
status = "okay";
clock-frequency = <100000>;
};
&i2c_bus3 {
status = "okay";
clock-frequency = <100000>;
#address-cells = <1>;
#size-cells = <0>;
goodix_ts@5d {
compatible = "goodix,gt9xx";
reg = <0x5f>;
gtp_resolution_x = <1024>;
gtp_resolution_y = <600>;
gtp_int_tarigger = <1>;
gtp_change_x2y = <0>;
gtp_overturn_x = <0>;
gtp_overturn_y = <0>;
gtp_send_cfg = <1>;
gtp_cfg_select = <0>;
gtp_touch_wakeup = <1>;
goodix_rst_gpio = <3>; // reset gpio0_3 = 8 * 0 + 3 = 3
goodix_irq_gpio = <4>; // int gpio0_4 = 8 * 0 + 4 = 4
/* mipi 7inch 1024x600 lcd touchscreen */
goodix,cfg-group0 = [
41 00 04 58 02 05 7D 00 01 2F 28
0F 50 32 03 05 00 00 00 00 00 00
00 18 1A 1E 14 89 0D 0C 2C 2A 0C
08 00 00 00 82 03 1D 0A 32 05 0A
32 00 00 00 00 00 0B 1E 50 94 E5
02 08 00 00 04 A7 21 00 8B 28 00
73 31 00 62 3B 00 52 48 00 52 00
00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 32 50 00
00 00 1C 1A 18 16 14 12 10 0E 0C
0A 08 06 04 02 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 2A
29 28 26 24 22 21 20 1F 1E 1D 18
16 14 13 12 10 0F 0C 0A 08 06 FF
FF FF FF 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 3B 01
];
/* mipi 8inch 800x1280 lcd touchscreen */
goodix,cfg-group1 = [
45 20 03 00 05 05 35 00 01 C8
1E 0F 50 32 03 05 00 00 00 00
00 00 04 18 1A 1E 14 8C 2E 0E
1E 20 EB 04 00 00 00 BA 02 2D
00 00 00 00 00 03 00 00 00 00
00 0F 2D 94 D5 02 07 00 00 04
E6 10 00 BB 14 00 92 1A 00 78
20 00 61 28 00 61 00 00 00 00
00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00
00 00 1C 1A 18 16 14 12 10 0E
0C 0A 08 06 04 02 00 00 00 00
00 00 00 00 00 00 00 00 00 00
00 00 2A 29 28 26 24 22 21 20
1F 1E 1D 1C 18 16 00 02 04 06
08 0A 0C 0F 10 12 13 14 00 00
00 00 00 00 00 00 00 00 00 00
00 00 00 00 CB 01
];
/* mipi 10inch 800x1280 lcd touchscreen */
goodix,cfg-group2 = [
00 20 03 00 05 0A 05 00 01 08
28 05 50 32 03 05 00 00 00 00
00 00 00 00 00 00 00 90 30 AA
17 15 31 0D 00 00 01 B9 04 25
00 00 00 00 00 00 00 00 00 00
00 0F 23 94 C5 02 07 00 00 04
9F 10 00 8B 13 00 7C 16 00 6B
1B 00 60 20 00 60 00 00 00 00
00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00
00 00 19 18 17 16 15 14 11 10
0F 0E 0D 0C 09 08 07 06 05 04
01 00 00 00 00 00 00 00 00 00
00 00 2A 29 28 27 26 25 24 23
22 21 20 1F 1E 1C 1B 19 00 02
04 06 07 08 0A 0C 0D 0E 0F 10
11 12 13 14 00 00 00 00 00 00
00 00 00 00 96 01
];
/* mipi 5inch 720x1280 lcd touchscreen */
goodix,cfg-group3 = [
];
/* mipi 4inch 480x800 lcd touchscreen */
goodix,cfg-group4 = [
];
/* mipi 5.5inch 720x1280 lcd touchscreen */
goodix,cfg-group36 = [
4C D0 02 00 05 05 34 00 01 40 00 0F 64 46 53 11
00 00 00 00 14 18 1A 1E 0A 04 00 00 00 00 00 00
00 00 14 00 00 00 00 00 00 00 00 64 1E 28 89 29
0A 53 55 C5 04 60 19 60 58 03 24 00 00 3C 78 C0
14 02 00 00 54 AE 46 9A 50 8B 5A 80 64 76 6E 6F
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 14 14 03 04 00 21 64 0A 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 53 30 64 5A 46 00 00 00 00 00 07 01 08 02
09 03 0A 04 0B 05 FF FF FF FF 01 02 03 04 05 06
07 08 09 12 11 10 0F 0E 0D 0C 0B 0A FF FF FF FF
FF FF FF FF 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 FF FF 04 33 00 00 00
02 00 19 28 00 00 5A 3C 00 00 00 13 C3 A3 01
];
};
gslx680@40 {
compatible = "gslX680_touch_back";
reg = <0x40>;
gtp_resolution_x = <800>;
gtp_resolution_y = <1280>;
gtp_change_x2y = <0>;
gtp_overturn_x = <0>;
gtp_overturn_y = <0>;
gtp_touch_wakeup = <1>;
touch-gpio = <4>;
reset-gpio = <3>;
};
goodix_gt1x@5d{
compatible = "goodix,gt1x";
reg = <0x5c>;//tmp address
gtp_resolution_x = <720>;
gtp_resolution_y = <1280>;
gtp_int_tarigger = <1>;
gtp_change_x2y = <0>;
gtp_overturn_x = <0>;
gtp_overturn_y = <0>;
gtp_send_cfg = <1>;
gtp_touch_wakeup = <1>;
goodix,rst-gpio = <3>;
goodix,irq-gpio = <4>;
goodix,cfg-group0 = [
4C D0 02 00 05 05 34 00 01 40 00 0F 64 46 53 11
00 00 00 00 14 18 1A 1E 0A 04 00 00 00 00 00 00
00 00 14 00 00 00 00 00 00 00 00 64 1E 28 89 29
0A 53 55 C5 04 60 19 60 58 03 24 00 00 3C 78 C0
14 02 00 00 54 AE 46 9A 50 8B 5A 80 64 76 6E 6F
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 14 14 03 04 00 21 64 0A 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 53 30 64 5A 46 00 00 00 00 00 07 01 08 02
09 03 0A 04 0B 05 FF FF FF FF 01 02 03 04 05 06
07 08 09 12 11 10 0F 0E 0D 0C 0B 0A FF FF FF FF
FF FF FF FF 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 FF FF 04 33 00 00 00
02 00 19 28 00 00 5A 3C 00 00 00 13 C3 A3 01];
};
};
&i2c_bus4 {
status = "okay";
clock-frequency = <100000>;
};
&i2c_bus5 {
status = "okay";
clock-frequency = <100000>;
};
&i2c_bus6 {
status = "okay";
clock-frequency = <100000>;
};
&i2c_bus7 {
status = "okay";
//clock-frequency = <100000>;
clock-frequency = <400000>;// change by rpdzkj fo use sample_dis
};
&spi_bus0{
status = "okay";
num-cs = <1>;
spidev@0 {
compatible = "rohm,dh2228fv";
reg = <0>;
pl022,interface = <0>;
pl022,com-mode = <0>;
spi-max-frequency = <50000000>;
};
};
&spi_bus1{
status = "okay";
num-cs = <2>;
spidev@0 {
compatible = "rohm,dh2228fv";
reg = <0>;
pl022,interface = <0>;
pl022,com-mode = <0>;
spi-max-frequency = <50000000>;
};
spidev@1 {
compatible = "rohm,dh2228fv";
reg = <1>;
pl022,interface = <0>;
pl022,com-mode = <0>;
spi-max-frequency = <50000000>;
};
};
&spi_bus2{
status = "okay";
num-cs = <1>;
spidev@0 {
compatible = "rohm,dh2228fv";
reg = <0>;
pl022,interface = <0>;
pl022,com-mode = <0>;
spi-max-frequency = <50000000>;
};
};
#endif
&mdio0 {
hisilicon,phy-reset-delays-us = <10000 20000 150000>;
phy0: ethernet-phy@1 {
reg = <1>;
};
};
&hisi_femac0 {
mac-address = [00 00 00 00 00 00];
phy-mode = "rmii";
phy-handle = <&phy0>;
status = "okay";
};
&hisfc {
hi_sfc {
compatible = "jedec,spi-nor";
reg = <0>;
spi-max-frequency = <160000000>;
};
};
&hisnfc {
hinand {
compatible = "jedec,spi-nand";
reg = <0>;
spi-max-frequency = <160000000>;
};
};
&mmc0 {
#ifdef CONFIG_MTD
status = "disabled";
#else
status = "okay";
#endif
};
&mmc1 {
status = "okay";
};
&mmc2 {
status = "okay";
};
&hidmac {
status = "disabled";
};
&gpio_chip0 {
status = "okay";
};
&gpio_chip1 {
status = "okay";
};
&gpio_chip2 {
status = "okay";
};
&gpio_chip3 {
status = "okay";
};
&gpio_chip4 {
status = "okay";
};
&gpio_chip5 {
status = "okay";
};
&gpio_chip6 {
status = "okay";
};
&gpio_chip7 {
status = "okay";
};
&gpio_chip8 {
status = "okay";
};
&gpio_chip9 {
status = "okay";
};
&gpio_chip10 {
status = "okay";
};
&gpio_chip11 {
status = "okay";
};
(4)一般一个节点描述一个硬件模块,但是不是所有硬件模块都需要dts来描述,usb或emmc等可以自己探测
4、property属性格式
(1)每个property就是一个key value对,property-name就是key
(2)属性可以有值或者没有值
[label:] prooerty-name = value; //有值
[label:]property-name; //没有值
(3)value的几种可能情况
字符串 compatible = "arm,cortex-a7";
32位无符号整数 reg = <1 0x123456 100>
16进制字节序列 reg = [00 11 22 33] //每个数据必须是2位,也可以附加上0x
字符串列表 compatible = "fsl,imx6ull-gpmi-nand", "fsl,imx6ul-gpmi-nand";
5、常见预定义标准属性
(1)compatible,节点数据将来去匹配内核策略部分的兼容性设置
案例1:compatible = "manufacturer, model"
案例2:compatible = "fsl, imx6ul-evk-wm8960", "fsl, imx-audio-wm8960"
案例3:16dv300的串口uart
注意1:根节点的compatible属性是确认内核是否适配该dtb的,作用类似于老版本的machine id;而设备节点的compatible属性是为了匹配Linux内核中的驱动程序,作用类似于以前驱动程序中设备结构体的.name
注意2:compatible如果有多个,前面的更精准,后面的越来越泛化,所以优先匹配前面,例如设备节点的compatible值有两个字符串,如果第一个匹配不上则会去匹配第二个,如下图所示:
(2)model,描述设备模块信息,比如名字、详细版本号
案例1:model = "wm8960-audio-V1.0"
案例2:model = "Hisilicon HI3516DV300 DEMO Board"
(3)status,描述设备状态信息,有以下几个值
"okey" 表示设备是可操作的
"disabled" 表示当前不可操作,但是后续是可以更改为可操作性的
"fail" "failed" 表示有严重错误,几乎不可能再可操作了
所有的属性赋值,后面的会覆盖前面的赋值;编译生成的二进制镜像文件是最后赋值状态;
(4)reg,配置某个硬件模块对应的地址范围信息,reg是region
#address-cells = <1> // 表示reg里面的数据address占用一个字长,注意字长不是字节
#size-cells = <1> // 表示reg里面的数据size占用一个字长,注意字长不是字节,为0表示只需要起始地址,不需要长度
gpio-spi: gpio_spi@0{
compatible = ".spi"
reg = <address1 length1 address2 length2 ......>
//address一般用来表示起始地址,length一般表示持续长度
}
实例参考16dv300的dts(上面已经提供了该文件)
6、中断描述的属性
(1)interrupt-controller 无值属性,表示这是个中断控制器node
(2)#interrupt-cells 这是中断控制器节点的属性,用来标识这个控制器需要几个cell做中断描述符,如中断号,中断有几种触发方式,所以其值至少为2
(3)interrupt-parent 标识此设备节点属于哪一个中断控制器,如果没有这个属性,会自动依附父节点
(4)interrupts 一个中断标识符列表,表示每一个中断输出信号,其中数据的个数与#interrupt-cells设置的相符合
拓展了解:GIC
https://zhuanlan.zhihu.com/p/166640956
https://blog.csdn.net/sunsissy/article/details/73791470
注:本资料大部分由朱老师物联网大讲堂课程笔记整理而来并且引用了部分他人博客的内容,如有侵权,联系删除!水平有限,如有错误,欢迎各位在评论区交流。