00. Table of Contents
Article directory
01. Overview
The device tree was introduced in later versions of Linux 3.x. The device tree is used to describe the board-level details of a hardware platform. The driver we write later needs to rely on the device tree, so here we first demonstrate how to compile and load the device tree.
For specific principles, please refer to Linux device tree related blogs.
02. Device tree compilation
2.1 Compile using the dtc tool in the kernel
First we need to compile the kernel (usually we only need to compile the kernel once, and the dtc tool will be generated when compiling the kernel). The location of the kernel compilation is in the directory, and the location of the kernel
dtc tool in the kernel is kernel/scripts/dtc/dtc
.
The usage of dtc tool is as follows
deng@local:~/code/x3399$ ./kernel/scripts/dtc/dtc --help
Usage: dtc [options] <input file>
Options: -[qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@Ahv]
-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 17 (for dtb and asm output)
-d, --out-dependency <arg>
Output dependency file
-R, --reserve <arg>
Make 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)
-a, --align <arg>
Make the blob align to the <bytes> (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-")
-@, --symbols
Enable generation of symbols
-A, --auto-alias
Enable auto-alias of labels
-h, --help
Print this help and exit
-v, --version
Print version and exit
deng@local:~/code/x3399$
Examples of using the dtc tool are as follows :
# 编译 dts 为 dtb
kernel/scripts/dtc/dtc -I dts -O dtb -o xxx.dtb xxx.dts
Actual usage example, here is pseudo code, for reference only, just understand it:
kernel/scripts/dtc/dtc -I dts -O dtb -o x3399-linux.dtb x3399-linux.dts
The command for the kernel to use the dtc tool is roughly as shown above. In fact, there are many dependencies in the device tree. These dependencies are processed through Makefile files. Therefore, in general, the device tree can be compiled not only through a dtc command. from.
2.2 Compile the device tree in the kernel source code (recommended)
We can try to compile the device tree through the kernel build script, and the device tree files we want to use are stored in /home/deng/code/x3399/kernel/arch/arm64/boot/dts/
it.
As mentioned earlier, the device tree will be automatically compiled when compiling the kernel, but compiling the kernel is time-consuming, so we recommend using the following command to compile only the device tree.
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- npi_v7_defconfig
make ARCH=arm -j4 CROSS_COMPILE=arm-linux-gnueabihf- dtbs
Example:
deng@local:~/code/x3399/kernel$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- i3399_defconfig
deng@local:~/code/x3399/kernel$ make ARCH=arm64 -j4 CROSS_COMPILE=aarch64-linux-gnu- dtbs
If it is executed in the kernel source code make distclean
, you must execute the first command, which is used to generate the default configuration file. If it is executed once, there is no need to execute it again. Of course, there is no problem if it is executed again. The second command starts to compile the device tree. The parameter "-j4" specifies how many threads to compile. Set it according to the actual situation of your computer. The larger the number, the faster the compilation. Of course, you don't need to set it. Device tree compilation is inherently fast.
The device tree file (.dtb) generated after successful compilation is located in the source code directory 内核源码/arch/arm64/boot/dts
. The name of the device tree file adapted to the development board is x3399-linux.dtb
.
/home/deng/code/x3399/kernel/arch/arm64/boot/dts/rockchip
03. Load device tree
3.1 Device tree loading method
There are several ways to replace the device tree.
- The first one is simple and direct. The device tree is compiled into the kernel, so reprogramming the kernel is definitely feasible. However, burning the kernel is troublesome, so I don’t recommend it and don’t explain it too much.
- The second is to replace the original one in the development board with the device tree or device tree plug-in we compiled.
We only introduce the second method, which is to replace the compiled new device tree file with the old device tree file in the corresponding directory of the development board.
3.2 Check the device tree loading status
We added a new node to the original device tree, led_test
and there is a device under this node rgb_led_red
. We can load it in the following way and check whether the new device tree has taken effect and whether the new node has been added.
Copy the compiled device tree to the development board through SCP or NFS. Replace /usr/lib/linux-image-4.19.35-imx6/imx6ull-mmc-npi.dtb .
When uboot is started, it is responsible for loading the device files in this directory into memory for kernel analysis. Enter sudo reboot
the command to restart the development board.
The device tree nodes in the device tree have corresponding files in the file system, located in the "/proc/device-tree" directory. Enter the "/proc/device-tree" directory as shown below.
[root@rk3399:/]# ls /proc/device-tree/
'#address-cells' power-management@ff310000
'#size-cells' psci
__symbols__ pwm@ff420000
adc-keys pwm@ff420010
aliases pwm@ff420020
amba pwm@ff420030
backlight qos@ffa58000
chosen qos@ffa5c000
cif_isp@ff910000 qos@ffa60080
cif_isp@ff920000 qos@ffa60100
clock-controller@ff760000 qos@ffa60180
compatible qos@ffa70000
cpuinfo qos@ffa70080
cpus qos@ffa74000
ddr_timing qos@ffa76000
dfi@ff630000 qos@ffa90000
display-subsystem qos@ffa98000
dmc qos@ffaa0000
dp-sound qos@ffaa0080
dp@fec00000 qos@ffaa8000
dsi@ff960000 qos@ffaa8080
dsi@ff968000 qos@ffab0000
dummy-codec qos@ffab0080
dummy_cpll qos@ffab8000
dummy_vpll qos@ffac0000
dw-hdmi-audio qos@ffac0080
dwmmc@fe310000 qos@ffac8000
dwmmc@fe320000 qos@ffac8080
edp@ff970000 qos@ffad0000
efuse@ff690000 qos@ffad8080
energy-costs qos@ffae0000
es8323-sound ramoops
ethernet@fe300000 reserved-memory
external-camera-clock rga@ff680000
external-gmac-clock rkisp1@ff910000
fiq-debugger rkisp1@ff920000
gpio-keys rktimer@ff850000
gpu@ff9a0000 rkvdec@ff660000
hdmi-hdcp2@ff988000 rockchip-i2s-sound
hdmi-sound rockchip-suspend
hdmi@ff940000 rockchip-system-monitor
i2c@ff110000 saradc@ff100000
i2c@ff120000 sdhci@fe330000
i2c@ff130000 sdio-pwrseq
i2c@ff140000 serial-number
i2c@ff150000 serial@ff180000
i2c@ff160000 serial@ff190000
i2c@ff3c0000 serial@ff1a0000
i2c@ff3d0000 serial@ff1b0000
i2c@ff3e0000 serial@ff370000
i2s@ff880000 spdif-out
i2s@ff890000 spdif-sound
i2s@ff8a0000 spdif@ff870000
iep@ff670000 spi@ff1c0000
interrupt-controller@fee00000 spi@ff1d0000
interrupt-parent spi@ff1e0000
iommu@ff650800 spi@ff1f0000
iommu@ff660480 spi@ff200000
iommu@ff670800 spi@ff350000
iommu@ff8f3f00 syscon@ff320000
iommu@ff903f00 syscon@ff770000
iommu@ff914000 test-power
iommu@ff924000 thermal-zones
leds timer
memory tsadc@ff260000
mipi-dphy-tx1rx1@ff968000 usb0
model usb1
name usb@fe340000
nocp-cci-msch0@ffa86000 usb@fe380000
nocp-cci-msch1@ffa8e000 usb@fe3a0000
nocp-gpu-msch0@ffa86400 usb@fe3c0000
nocp-gpu-msch1@ffa8e400 usb@fe3e0000
nocp-hp-msch0@ffa86800 vcc-phy-regulator
nocp-hp-msch1@ffa8e800 vcc-sd
nocp-lp-msch0@ffa86c00 vcc3v3-sys
nocp-lp-msch1@ffa8ec00 vcc5v0-host-regulator
nocp-video-msch0@ffa87000 vcc5v0-sys
nocp-video-msch1@ffa8f000 vccadc-ref
nocp-vio0-msch0@ffa87400 vdd-log
nocp-vio0-msch1@ffa8f400 vop@ff8f0000
nocp-vio1-msch0@ffa87800 vop@ff900000
nocp-vio1-msch1@ffa8f800 voppwm@ff8f01a0
opp-table0 voppwm@ff9001a0
opp-table1 vpu_service@ff650000
opp-table2 watchdog@ff848000
opp-table3 wireless-bluetooth
pcie-phy wireless-wlan
pcie@f8000000 xgpio_beep
phy@ff7c0000 xgpio_fan
phy@ff800000 xgpio_hdmiin_spken
pinctrl xgpio_pwr4g
pmu-clock-controller@ff750000 xin24m
pmu_a53 xin32k
pmu_a72
[root@rk3399:/]#
Then enter the xgpio_beep folder, and you can find the attributes defined in the beep node and its child nodes, as shown below.
[root@rk3399:/sys/firmware/devicetree/base/xgpio_beep]# pwd
/proc/device-tree/xgpio_beep
[root@rk3399:/sys/firmware/devicetree/base/xgpio_beep]# ls
compatible gpio name pinctrl-0 pinctrl-names status
[root@rk3399:/sys/firmware/devicetree/base/xgpio_beep]#
There is an additional name in the node attributes. We have not defined the name attribute in the led node to save the node name.
The attribute here is a file, and the child node is a folder, and we enter the "xgpio_beep" folder again. There are four property files: compatible name reg status. We can view these properties files using the “cat” command as shown below.
[root@rk3399:/sys/firmware/devicetree/base/xgpio_beep]# cat name
xgpio_beep
At this point, the device tree is loaded successfully.
04. Compilation and loading of device tree plug-in
Dynamic DeviceTree (Dynamic DeviceTree) was introduced after Linux 4.4. Device tree plug-ins are dynamically loaded into the system for recognition by the kernel. When compiling the device tree plug-in, there is no need to recompile the entire device tree plug-in, only the part we modified needs to be compiled.
Note that the device tree plug-in and the device tree do not replace each other, but complement each other. The device tree plug-in can dynamically expand functions not described in the main device tree after the main device tree is finalized. For example, if the device tree of board A does not enable the function of serial port 1, but board B needs to enable the function of serial port 1, you can directly use the device tree of board A and use the device tree plug-in to expand serial port 1 to meet the needs of board B.
4.1 Compile the device tree plug-in in the kernel
The device tree plug-in is compiled using the DTC tool like the device tree, except that the device tree is compiled into .dtb. The device tree plug-in needs to be compiled into .dtbo. We can use the DTC compilation command to compile and generate .dtbo, but this is more cumbersome and error-prone.
We also complete the compilation of the device tree plug-in dtbo during kernel compilation. Of course, we can also compile the device tree plug-in dtbo when we compile the device tree separately.
We provide a large number of device tree plug-ins in the kernel. For some development boards, many peripheral hardware descriptions are provided in the form of dtbo plug-ins. This is very flexible to use.
deng@local:~/code/x3399/kernel/arch/arm64/boot/dts/rockchip$ pwd
/home/deng/code/x3399/kernel/arch/arm64/boot/dts/rockchip
deng@local:~/code/x3399/kernel/arch/arm64/boot/dts/rockchip$ ls Makefile
Makefile
deng@local:~/code/x3399/kernel/arch/arm64/boot/dts/rockchip$
When you try to write a device tree plug-in, you can add your own device tree plug-in to the: arch/arm/boot/dts/overlays
directory, modify arch/arm/boot/dts/overlays/Makefile
the file, and add compilation options in the form of imx-rgb-led.dtbo. Just append imx-rgb-led.dtbo to imx-uart8.dtbo.
After adding it, you can execute the compilation command of the device tree, and the compilation of the device tree plug-in will be completed simultaneously.
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- npi_v7_defconfig
make ARCH=arm -j4 CROSS_COMPILE=arm-linux-gnueabihf- dtbs
It can be seen that when compiling and outputting, the dtbo file also has corresponding printing information.
4.2 Kernel compilation device tree plug-in process
Compiling the device tree plug-in is similar to compiling the device tree. Here we introduce the process of compiling the device tree plug-in using the dtc tool in the kernel.
Example of the process of compiling xxx.dts into xxx.dtbo in the kernel, for reference only:
内核构建目录/scripts/dtc/dtc -I dts -O dtb -o xxx.dtbo xxx.dts
For example, compile rgb-led-overlay.dts to rgb.dtbo
../ebf_linux_kernel/build_image/build/scripts/dtc/dtc -I dts -O dtb -o rgb.dtbo rgb-led-overlay.dts
The compiled device tree plug-in is rgb.dtbo.
Of course, just like compiling the device tree, the compilation of the device tree plug-in also involves dependencies, so the compilation process is also more complicated. Compilation can be completed with more than just one command.