设备树诞生背景:硬件设备中种类逐年递增,板级platform平台设备文件越来越多。
设备树由根节点开始,可以包含若干个子节点;每个子节点又可以包含若干个子节点。
DTS(device tree source):设备树源文件,ASCII格式。
DTC(device tree compiler):设备树编译工具,将dts文件编译成dtb文件。
DTB(device tree blob):二进制设备树。
设备树使用:uboot负责加载dtb文件到内存的特定位置,内核在启动时从这个位置获取dtb文件并解析使用。
野火imx 6ull的pro开发板的设备树源文件dts存放在内核/arch/arm/boot/dts/imx6ull-mmc-npi.dts。
设备树编译工具(内核主目录下执行)
内核编译
#进行内核配置
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- npi_v7_defconfig
#编译dts
make ARCH=arm -j4 CROSS_COMPILE=arm-linux-gnueabihf- dtbs
手动编译
#编译dts为dtb
./scripts/dtc/dtc -I dts -O dtb -o xxx.dtb arch/arm/boot/dts/xxx.dts
#反编译dtb为dts
./scripts/dtc/dtc -I dtb -O dts -o xxx.dts arch/arm/boot/dts/xxx.dtb
#-I:指定输入格式
#-O:指定输出格式
#-o:指定输出文件
设备树框架
从上到下
头文件
#include <dt-bindings/input/input.h>
#include "imx6ull.dtsi"
主体
注意,.dtsi文件中也有/根节点。经过内核解析后会和主题的根节点合并。
/ {
model = "Embedfire i.MX6ULL Board";
compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ull";
aliases {
pwm0 = &pwm1;
pwm1 = &pwm2;
pwm2 = &pwm3;
pwm3 = &pwm4;
};
chosen {
stdout-path = &uart1;
};
memory {
reg = <0x80000000 0x20000000>;
};
reserved-memory {
#address-cells = <1>;
#size-cells = <1>;
ranges;
linux,cma {
compatible = "shared-dma-pool";
reusable;
size = <0x14000000>;
linux,cma-default;
};
};
regulators {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <0>;
reg_sd1_vmmc: regulator@1 {
compatible = "regulator-fixed";
regulator-name = "VSD_3V3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>;
off-on-delay = <20000>;
enable-active-high;
};
/*
reg_gpio_dvfs: regulator-gpio {
compatible = "regulator-gpio";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_dvfs>;
regulator-min-microvolt = <1300000>;
regulator-max-microvolt = <1400000>;
regulator-name = "gpio_dvfs";
regulator-type = "voltage";
gpios = <&gpio5 3 GPIO_ACTIVE_HIGH>;
states = <1300000 0x1 1400000 0x0>;
};
*/
};
leds {
compatible = "gpio-leds";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_led>;
led0: cpu {
label = "cpu";
gpios = <&gpio5 3 GPIO_ACTIVE_LOW>;
default-state = "on";
linux,default-trigger = "heartbeat";
};
};
/* External sound card */
sound: sound {
status = "disabled";
};
spi4: 74hc595 {
compatible = "spi-gpio";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_spi4>;
pinctrl-assert-gpios = <&gpio5 8 GPIO_ACTIVE_LOW>;
status = "disabled";
gpio-sck = <&gpio5 11 0>;
gpio-mosi = <&gpio5 10 0>;
cs-gpios = <&gpio5 7 0>;
num-chipselects = <1>;
#address-cells = <1>;
#size-cells = <0>;
gpio_spi: gpio_spi@0 {
compatible = "fairchild,74hc595";
gpio-controller;
#gpio-cells = <2>;
reg = <0>;
registers-number = <1>;
registers-default = /bits/ 8 <0x57>;
spi-max-frequency = <100000>;
};
};
};
//截取部分
多个根节点合并。
根节点下包含多个子节点。
子节点追加内容
若要对某个节点A追加内容,只需增设&A节点即可,&A节点内容就是要追加的内容。A是节点标签,而且追加节点要放在根节点的外面。
&cpu0 {
/*dc-supply = <®_gpio_dvfs>;*/
clock-frequency = <800000000>;
};
&clks {
assigned-clocks = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
assigned-clock-rates = <786432000>;
};
&fec1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_enet1>;
phy-mode = "rmii";
phy-handle = <ðphy0>;
status = "okay";
};
...
节点命令
基本方法
node-name@unit-address{
属性1 = …
属性2 = …
属性3= …
子节点…
}
node-name:指定节点的名称unit-address:用于指定“单元地址”
节点标签
cpu0: cpu@0 {
compatible = "arm,cortex-a7";
device_type = "cpu";
reg = <0>;
}
cpu0:标签,为节点名称起一个别名。
在追加节点、引用节点时,都要使用该节点的标签。
别名子节点
aliases {
can0 = &flexcan1;
can1 = &flexcan2;
ethernet0 = &fec1;
ethernet1 = &fec2;
...
}
与节点标签不同的是:别名子节点可以批量地为若干个节点规定别名。
从外到内
常见通用节点属性(供所有外设使用)
compatible属性
属性值类型:字符串
主要用来匹配驱动。
设备树中的节点,若是有compatile属性,内核会为其生成一个struct device结构体。
intc: interrupt-controller@a01000 {
compatible = "arm,cortex-a7-gic";
#interrupt-cells = <3>;
interrupt-controller;
reg = <0xa01000 0x1000>,
<0xa02000 0x100>;
};
arm:芯片厂商cortex-a7-gic:模块对应的驱动名字
一个节点的 compatible
也可以设置多个属性值,如此可以和多个驱动匹配。
/ {
model = "Gateworks Ventana i.MX6 Dual/Quad GW51XX";
compatible = "gw,imx6q-gw51xx", "gw,ventana", "fsl,imx6q";
};
model属性
属性值类型:字符串
用来准确描述当前板子型号信息。
model = "Embedfire i.MX6ULL Board";
status属性
属性值类型:字符串
用来描述设备运行状态。
状态值 | 描述 |
“okay” | 设备正常运行 |
“disabled” | 该设备目前尚未运行,但它可能在未来开始运行(例如,某些东西没有插入或关闭) |
“fail” | 设备不可操作 |
“fail-sss” | 设备不可操作,原因是设备中检测到一个严重的错误,如果没有修复,它就不太可能运行。“sss”的值指示具体的错误原因 |
reg属性
属性值类型:一系列<地址、长度>对
ocrams: sram@900000 {
compatible = "fsl,lpm-sram";
reg = <0x900000 0x4000>;
};
地址:外设寄存器组的起始地址。
长度:外设寄存器组的字节长度。
#address-cells和#size-cells属性
属性值类型:u32
#address-cells:设置子节点中reg地址的数量,通常取值为1。
#size-cells:设置子节点中reg地址的长度的数量,通常取值为1或者0。
soc {
#address-cells = <1>;
#size-cells = <0>;
compatible = "simple-bus";
interrupt-parent = <&gpc>;
ranges;
ocrams: sram@900000 {
compatible = "fsl,lpm-sram";
reg = <0x900000>;
};
};
linux系统中查看设备树(板子linux)
以目录的形式体现设备树结构。有两个目录,都可以查看。
ls /sys/firmware/devicetree/base
ls /proc/device-tree