Happy new year 2020.
For three days, I read the device tree source (dts) of Raspberry Pi 4. I'm still reading it, so I'll give you some information about it somewhere, but this time I'll introduce the tricks I used to read dts.
TL;DR
--dts with #include
will be easier to read through cpp and dtc
devicetree (hereafter dt) describes where and what device is connected to a particular piece of hardware.
In Linux, dt is mainly used to know the configuration of embedded machines using ARM and PowerPC, and Raspberry Pi also uses this dt to teach the Linux Kernel the configuration of the machine.
Like a compiled language, dt compiles a devicetree source (hereafter dts) written in a human-readable format with a devicetree compiler (hereafter dtc) to generate a devicetree blob (hereafter dtb) and use it. To do.
For example, in the Linux kernel (ARM), the address of dtb loaded in memory in advance by a boot loader etc. is received via a register, and the dtb in memory is referenced to know the machine configuration.
For other details about dt, refer to the following.
The BCM2711 SoC installed in the Raspberry Pi 4 has several parts that are different from the SoC up to the Raspberry Pi 3, such as installing the GIC-400 in the interrupt controller.
However, the Peripheral Manual that explains the peripherals installed in the SoC and how to handle them has not been released yet (as of July 2019, "It is almost completed, but it seems that it will take several weeks" Middle Written by a person has not yet appeared as of January 6, 2020) ..
Therefore, in order to do something like bare metal development that directly controls peripherals on Raspberry Pi 4, you can find it in Linux Kernel Source for Raspberry Pi. You need to look at the dts to find out the peripheral configuration and the mapped address of the MMIO.
Dts for Raspberry Pi 4 is published below.
The first few lines of this dts file are quoted below.
#include "bcm2711.dtsi"
#include "bcm2711-rpi.dtsi"
#include "bcm283x-rpi-csi1-2lane.dtsi"
As you can see from this, bcm2711-rpi-4-b.dts uses the include statement to read multiple dtsi files.
And the bcm2711.dtsi read here also reads bcm2838.dtsi, that is, the include is nested, so it is a little troublesome to read it as it is.
Therefore, I would like to create a dts file for reading with the include expanded in advance.
Bring the Linux kernel for the Raspberry Pi from git and put it in that directory.
$ git clone --depth=1 https://github.com/raspberrypi/linux raspberrypi_linux
$ cd raspberrypi_linux
In dtc used when setting dts to dtb, it is possible to output dts with dts as input. Therefore, I thought, "If you pass dtc, include should be processed properly and you should get dts that is easy to read ...", but when I try to execute it, the following error appears and it does not work.
$ dtc -I dts -O dts -o readable.dts arch/arm/boot/dts/bcm2711-rpi-4-b.dts
Error: arch/arm/boot/dts/bcm2711-rpi-4-b.dts:3.1-9 syntax error
FATAL ERROR: Unable to parse input tree
See Devicetree Specification Release v0.2 to find the cause. , "6.1 Compiler directives" states that include in dts should be done in the following format.
/include/ "FILE"
On the other hand, in bcm2711-rpi-4-b.dts, dtc seems to give an error because it is not included in the format written in the device tree specification.
From the results of the investigation so far, it should be correct that dts cannot be compiled with the include statement of bcm2711-rpi-4-b.dts. But why is it possible to compile dts on Linux?
Looking up the dtb build rules from the Linux source code for the reason, [scripts / Makefile.lib](https://github.com/raspberrypi/linux/blob/rpi-4.19.y/scripts/ From Makefile.lib # L287), I found that in Linux, dts is passed through the C preprocessor before compiling with dtk. The relevant part of scripts / Makefile.lib is quoted below.
cmd_dtc = mkdir -p $(dir ${dtc-tmp}) ; \
$(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \
$(DTC) -O dtb -o $@ -b 0 \
$(addprefix -i,$(dir $<) $(DTC_INCLUDE)) $(DTC_FLAGS) \
-d $(depfile).dtc.tmp $(dtc-tmp) ; \
cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile)
Therefore, referring to this rule, it seems that easy-to-read dts can be obtained by passing dts through the preprocessor with appropriate options and then compiling with dtc.
From here, let's make dts that is easy to read by referring to the procedure that Linux is doing.
To handle the include, pass it through the preprocessor as follows.
cpp -nostdinc -undef -D__DTS__ -x assembler-with-cpp \
-I./scripts/dtc/include-prefixes \
./arch/arm/boot/dts/bcm2711-rpi-4-b.dts \
-o ~/bcm2711-rpi-4-b_readable.dts
dtc
It is difficult to read because there are many comments attached by the preprocessor just by passing it through the preprocessor, so compile it with dtc to make it easier to read.
dtc -I dts -O dts -o ~/bcm2711-rpi-4-b_readable.dts ~/bcm2711-rpi-4-b_readable.dts
I get a lot of warnings, but if there are no errors, there should be dts that are easier to read in ~ / bcm2711-rpi-4-b_readable.dts
.
This concludes the introduction of how to make easy-to-read dts with expanded include.
When reading dts on Raspberry Pi 4,
"The compatible head of gpio is bcm2711-gpio, but since bcm2835-gpio is also included, the code for RasPi3 seems to work thanks to the compatibility. But what's new? Driver. I have to read ... "
It's fun to discover and think about things like that.
I hope you can share this fun with the people who read this article.
Recommended Posts