Automatic generation of DTS file for Zedboard/ZC702 (Zynq-7000)

This post was written by eli on July 31, 2012
Posted Under: ARM,FPGA,Zynq

Background

Creating a DTS file is a crucial step in integrating a custom peripheral with the Linux kernel. Unfortunately, this subject is rather hazy at the present time, and it’s in particular difficult to obtain that initial DTS to boot the system up with for the first time.

It’s important to take the DTS (and the DTB compiled from it) for what it is: A simple data tree (think XML) containing information that is read by the kernel as it boots up. By convention, some standard entries tell it what resources (memory and interrupts) to allocate, and the rest of them can be read by the specific driver to obtain application-specific information (e.g. the clock frequency driving the hardware). Like XML, you’re free to add whatever nodes you want to the tree, as long as you have reason enough to assume their names aren’t used for something else.

As of writing this post, there is no automatic process for generating a DTS that includes custom peripherals for Zynq. On the other hand, it’s not all that difficult to add the entry manually, when all the other hardware peripheral’s nodes are available. The two methods described below take different approaches: The first reverse-engineers the DTS from an existing, running Linux kernel. If custom peripherals are declared in the loaded DTB, they will appear here. The significant drawback of this method is that pointers to other nodes in the tree (e.g. “interrupt-parent”) appear as numeric values, and not by a name reference, which makes the whole thing harder to understand and more fragile to changes. Also note that if there are differences in the processor configuration between the running system and yours, this device tree will not be useful. But it’s an excellent way to verify the small details are in place.

The second method focuses on getting the device tree from a system configuration in Xilinx’ EDK. This ensures a perfect match between the processor configuration and the device tree, but if the driver expects some extra attributes, they may get missed. In theory, these attributes should be generated automatically from the IP core’s attributes, but there is nothing stopping the driver’s author from manually editing the DTS tree to add hints to the driver.

I’ve already written a general post on device trees for Microblaze (and several general info). But the principles are the same for any processor. I should mention, that it was written before kernel 3.3, which seems to have another notation for interrupts.

I’ve also described how to run the process for a Microblaze processor in a previous post, which is the basis for this one.

I assume ISE 14.2, but it’s probably not very relevant.

Method #1: Ask a running kernel

The /proc filesystem has a full outline of the device tree the kernel uses. So after booting the board with Linux, go something like

zynq> mount /dev/mmcblk0p1 /mnt/
zynq> cd /proc/
zynq> tar -czf /mnt/devtree.tar.gz device-tree
zynq> poweroff

In this example, I’ve assumed that the system was booted from the SD card, and the data is stored to it.

After the board has powered off, attach the SD card to your computer, and copy the devtree.tar.gz to some Linux kernel source’s root directory. From there, go:

$ tar -xzf devtree.tar.gz
$ scripts/dtc/dtc -I fs -O dts -o reverse.dts device-tree/

And the reverse-engineered device tree is now given as reverse.dts. It’s recommended to remove all these files from the Linux source, just to avoid future confusion.

The truth is, that the DTS can be disassembled from the DTB with the same utility with something like

$ scripts/dtc/dtc -I dtb -O dts -o fromdtb.dts boot_with_this.dtb

But I prefer getting it from the running kernel for one simple reason: There’s often a chance for confusion regarding exactly which DTB file is loaded at bootup, with all those contradicting parameters fed into the boot loaders. The kernel just tells us what it got.

Method #2: Using Xilinx’ tools

For the sake of those who skipped the introduction:

The DTS file generated by the procedure described below is not good for direct use. See remarks above.

In fact, peripherals in the PL (that is, implemented in logic fabric) don’t appear in the DTS. I suppose that’s why the Zynq-Linux wiki currenly says that there’s no support for automatic device tree generation.

But the actual configuration parameters appear to be consistent. So if not for direct use, the generated DTS files can at least help with verifying the used DTS file is consistent.

Anyhow, I’m pretty confident that this method will be OK some day, if not already, when the device-tree package gets up-to-date enough.

Preparations

First create a special directory, and make it the working directory of your shell.

The device tree file is generated automatically with the libgen utility with the help of a Tcl script. As of ISE 14.2, this script needs to be loaded separately with git:

bash> git clone git://git.xilinx.com/device-tree.git

This downloads the entire Git repository, and creates a single directory, ‘bsp’. Change the name of the directory inside it from ‘device-tree_v0_00_x’ to ‘device-tree’.

Another web page explains how to make SDK recognize the script, but I prefer command line for things like this.

Obtaining XML and MSS files

From the XPS, pick Project > Export Hardware Design to SDK. This may launch a full implementation process, but this can be avoided by unchecking “Include bitstream and BMM file” in the dialog box that appears on this request. Once the SDK is open (and just any workspace directory chosen),  go File > New > Xilinx Board Support package, and accept the defaults offered in the dialog boxes. That will, among others, produce an MSS file under e.g. standalone_bsp_0/ in the workspace directory. Copy that file (typically system.mss) so it’s alongside with ‘bsp’.

Then copy the XML file (typically system.xml) from the SDK\SDK_Export\hw directory, also alongside with ‘bsp’

Edit the copy you made of system.mss, so that the BEGIN OS to END part reads

BEGIN OS
 PARAMETER OS_NAME = device-tree
 PARAMETER PROC_INSTANCE = ps7_cortexa9_0
END

and not “standalone” for OS.

Creating the DTS file

Open a DOS Window or Linux prompt terminal with libgen in its PATH. The easiest way is to launch a “Xilinx shell” from the EDK’s project menu, Xilinx Tools > Launch Shell.

Navigate to the working directory, where the ‘bsp’ directory is. Just to avoid confusions, this is what a plain ‘dir’ command should say (more or less):

C:\experiments>dir
 Volume in drive C has no label.
 Volume Serial Number is 83E2-6332

 Directory of C:\experiments

07/31/2012  05:04 PM    <DIR>          .
07/31/2012  05:04 PM    <DIR>          ..
07/31/2012  04:52 PM    <DIR>          bsp
07/31/2012  03:55 PM             3,360 system.mss
07/31/2012  12:15 PM           639,484 system.xml
 2 File(s)        642,844 bytes
 3 Dir(s)   3,239,301,120 bytes free

And then run libgen as follows:

libgen -hw system.xml -lp device-tree -pe ps7_cortexa9_0 -log libgen.log system.mss

Which generates a xilinx.dts in ps7_cortexa9_0\libsrc\device-tree. Copy this file to arch/microblaze/boot/dts/ in the to-be compiled kernel source tree. If you can’t find the file there, and libgen didn’t complain about some error, you may have forgotten to edit system.mss as mentioned just above.

Reader Comments

Hello Eli,
thanks for your blog, is very helpful.
I have noticed a (at least for me) strange behaviour with the generated device tree. On my ZED board it is only booting when I change the alias line
“serial1 = &ps7_uart_1;”
to
“serial0 = &ps7_uart_1;”

Does that make any sense to you?
best regards,
Matthias

#1 
Written By Matthias on August 22nd, 2013 @ 08:35

Well, the question is what DTS file you’re using, with which kernel etc. I don’t have any alias on either serial0 or serial1 in my DTS (Xillinux).

If that really interests you, look where this alias is used. And then possibly grep the zynq and ARM related sources for the string.

#2 
Written By eli on August 22nd, 2013 @ 12:23

The strange thing is, the alias is not used in my DTS ??
(That seems to be some homework for me)

#3 
Written By Matthias on August 23rd, 2013 @ 13:47

Hi Matthias and Eli,
I had the same issue on a zc706 board. When I ran with the existing devicetree, the boot would start ok and then switch away from the serial port. When I followed Matthias suggestion, it booted up ok.
I think what is happening is the kernel (I’m using a petalinux kernel) switches to serial0 for console near the end of the boot process by default. This is normally ok, but on the zc706 (and ZED I assume), uart0 exists, but doesn’t go anywhere. The change above makes the kernel use &ps7_uart_1 (which goes to the CP2103) as the first serial port, or console. I’m sure you can change this in the kernel configuration as well as here, but this way makes the most sense.

BTW. Eli, thanks for this blog. It is really helpful. I don’t fully understand the devicetree yet, but at least I can get things working now.

cheers,
Greg

#4 
Written By Greg on February 13th, 2014 @ 01:24

please how do you generate dts file in vivado 2014.1 ?
there is no more xps, so no libgen

previous method create an empty directory an Makefile…

#5 
Written By raph on April 22nd, 2014 @ 23:12

Hi,

Frankly speaking, I haven’t been following up with what Xilinx offers in the field of automatic tools for obtaining a device tree. Whenever necessary, I write the entries manually.

#6 
Written By eli on April 23rd, 2014 @ 04:30

Hi,
When I want to generate the dts file, i get the following Error in the console:

Staging source files.
Running DRCs.
#————————————–
# device-tree BSP DRC…
#————————————–
Running generate.
#————————————–
# device-tree BSP generate…
#————————————–
ERROR:EDK:2950 –
Unknown MDT DataBase Function get_property
ERROR:EDK – device-tree () –
ERROR:EDK:3416 – Error(s) while running TCL procedure generate().

Can you help me with this?
Cheers Markus

#7 
Written By Markus on June 18th, 2014 @ 11:36

Hi,

As mentioned above, I’m not in sync with this tool for quite a while. Sorry.

#8 
Written By eli on June 18th, 2014 @ 12:16

Add a Comment

required, use real name
required, will not be published
optional, your blog address