This Embedded Linux Development Guide will provide some preliminary knowledge on how to build
Linux for Digilent boards based on the Zynq-7000TM All-Programmable System-on-Chip (ZYNQ AP
SoC) to suit your customized hardware designs. This guide takes a bottom-up approach by starting
from a hardware design on the ZYNQ AP SoC Board, moving through the necessary preliminary
processes, and eventually giving instructions for running and debugging the Linux kernel.
Section I: Hardware Customization begins with the Linux Hardware Design Package for ZYNQ AP
SoC boards, available on the Digilent Inc. website. This section then illustrates the ZYNQ AP SoC
basic architecture and explains how to create customized hardware using Xilinx Platform Studio (XPS)
available in the Xilinx ISE Design Suite WebPack.
Section II: Device Tree – Describe Your Hardware to the Linux Kernel examines how the Linux
kernel gathers information about the customized hardware. Section II takes a closer look at a data
structure called the Device Tree Blob (DTB), explains how to write a Device Tree Source (DTS) file,
and how to compile the source into a DTB file.
Section III: U-Boot – The Embedded Boot Loader introduces U-Boot, a popular boot loader for
Linux used by many embedded systems. Section III presents preliminary knowledge about how to
configure and build U-Boot, and provides an introduction of some commonly used U-Boot commands.
After explaining all the prerequisites for running The Linux kernel (boot loaders, device trees, etc.), the
guide moves to configuring the Linux kernel in Section IV: Linux Kernel Configuration. This section
demonstrates customizable features useful for custom hardware design. This section also provides
information for building and customizing the kernel, file system customization, and finally running the
Linux kernel on ZYNQ AP SoC based boards.
During the compilation and running of The Linux kernel on your customized hardware, there is a
chance that the kernel will panic and generate an Oops message or completely cease functioning.
The Appendix: How to Debug the Linux Kernel introduces you to some simple debugging
techniques to follow when errors occur with the Linux kernel.
Before creating custom hardware or using the Linux kernel, Digilent Inc. recommends that users have
some experience with embedded Linux development on other embedded systems or they have read
the Getting Started with Embedded Linux guide for their platform. Moreover, users can read this
documentation along with the Embedded Linux Hands-on Tutorial for their specific Zynq AP SoC
board. These documents are available on the Digilent Website, Embedded Linux page and the
webpage for your product.
page 1 of 23
Copyright Digilent, Inc. All rights reserved. Other product and company names mentioned may be trademarks of their respective owners.
Using Zynq with Linux
Processing System
Programmable Logic
Application Processor Unit
NEON/FPU Engine
MMU
Cortex-A9
MPCore
CPU
32KB I Cache 32KB D Cache
NEON/FPU Engine
MMU
Cortex-A9
MPCore
CPU
32KB I Cache 32KB D Cache
GICSnoop Control Unit
512KB L2 Cache & Controller
SWDT
TTC
SLCR
OCM
Interconnect
256KB OCM
BootROM
Central Interconnect
UART1
GPIO
SD0
USB0
Enet0
QSPI
AXI
Interconnect 0
(AXI_LITE)
Clock generator
AXI
DMA
AXI
DMA
AXI
VDMA
Axi_gpio
(ADAU1761)
Axi_i2s_adi
(ADAU1761)
Axi_iic
(ADAU1761)
Axi_spdif_tx
(ADV7511)
Axi_hdmi_tx_16b
(ADV7511)
Axi_iic
(ADV7511)
Axi
Interconnect 1
Axi
Interconnect 2
DDR2/3 Memory
Controller
512 MB
DDR3
PL to
Memory
Interconnect
Axi_clkgen
Section I: Hardware Customization
Before creating your customized hardware, we suggest you start with the Linux Hardware Design
Project available on your board’s Digilent product webpage. The reference design includes the proper
configuration for most of the peripheral devices available on-board your product including the interrupt
controller, timer, clock generator, AXI interconnects, etc. that are all essential for Linux to operate
properly.
Figure 1.System Architecture of Linux Hardware Design Project for ZedBoard
www.digilentinc.com page 2 of 23
Copyright Digilent, Inc. All rights reserved. Other product and company names mentioned may be trademarks of their respective owners.
Using Zynq with Linux
The Linux Hardware Design Project posted on the Digilent website usually contains the hardware
controllers for all of your product peripheral devices and the GPIO for extension pins (e.g. Pmods,
VHDC, FMC, etc.) Before you begin hardware customization, please read the documentation inside
the Linux Hardware Design for your product, which explains the hardware in detail, and the
Embedded Linux Hands-on Tutorial, which guides you through step by step instructions for making
changes to the reference hardware design.
First Stage Boot Loader (FSBL)
We discuss the First Stage Boot Loader (FSBL) here because of its integral relationship with
hardware design. Digilent recommends that you recompile the FSBL every time you make hardware
changes. The FSBL will do several simple initialization steps for the Processing System (PS), like
setting up a clock generator. It also has board-specific modifications that perform several initialization
steps for various on-board devices. For instance, the FSBL for the ZedBoard will toggle the reset pin
of USB-OTG to perform a reset before Linux gets loaded.
You just need to make a few clicks to generate the FSBL. The project guide within the Linux Hardware Design and hands-on tutorial for your specific board will guide you through it. You can also
refer to the ZYNQ Software Developers Guide available on the Xilinx website at www.xilinx.com.
www.digilentinc.com page 3 of 23
Copyright Digilent, Inc. All rights reserved. Other product and company names mentioned may be trademarks of their respective owners.
Section II: Device Tree – Describe Your Hardware to the Linux Kernel
The Linux Kernel is a piece of embedded standalone software running on your hardware. The kernel
provides a standardized interface for application programmers to utilize all hardware resources
without knowing the details. Thus, the kernel has to know every detail about the hardware it is working
on. The Linux Kernel uses the data structure known as Device Tree Blob (DTB) to describe your
hardware. Sometimes DTB is called Flat Device Tree (FDT), Device Tree Binary, or simply Device
Tree.1
Section II takes a closer look at the device tree and examines how the Linux kernel interprets and
understands your hardware.
Device Tree Source (DTS)
The Device Tree Source (DTS) file is the source file you use to create the device tree data structure
that passes to the kernel during kernel booting. The file is a simple tree structure comprised of nodes
and properties. Properties are key-value pairs, and nodes may contain both properties and child
nodes.2 (See Example 1.)
Example 1.
We abstracted the part of the device tree source code in Example 1 from the ZedBoard default device
tree source file. In the device tree source file “/” stands for the root node and everything inside the
1
Hallinan, Christopher. Embedded Linux primer: a practical, real-world approach. Upper Saddle River, NJ:
Prentice Hall, 2007.
2
http://devicetree.org/Device_Tree_Usage
www.digilentinc.com page 4 of 23
Copyright Digilent, Inc. All rights reserved. Other product and company names mentioned may be trademarks of their respective owners.
brackets “{}” are either properties of the root nodes or the children of the root node. In Example 1,
the first property of the root node is model. String “Xilinx Zynq ZED” is assigned to it. Property
compatible defines the compatibility of the node, and, in this case, is given the compatibility string
“xlnx,zynq-zed”; The children of the root nodes include the on-board DDR3 SDRAM,
ps7_ddr_0, and the central AXI interconnects for the whole system, ps7_axi_interconnect_0.
There are many more children of the root nodes in the default DTS file.
The following sub-sections introduce the basic structures of nodes and some of the most common
node properties. You can find more detailed information about the device tree under folder
Documentation/devicetree/ in the Linux kernel source.
Device Nodes
Example 2 demonstrates the basic structure of device nodes.
Example 2.
The Name field is the name you assigned to the device tree node. The name of the node is not
required, but should be unique in the whole tree if assigned. You can obtain the phandler of the
device node with the notation &(name).
The part (Generic Name)@(Base Address)actually forms the full name of the device node.
According to conventions, the full name of the device is usually a generic name followed by the base
address of the device. The Generic Name field describes the generic class of the device, such as
Ethernet, qspi, i2c, etc. The Base Address field gives the base address for the device node.
Some devices are virtual devices that do not have a physical memory mapped in the processor
memory space. For these devices, The code drops the @(Base Address) for devices with no
mapped physical memory. In Example 3, the leds defined in the DTS file does not have a base
address, because it utilizes a bit in the GPIO controller to control an on-board LED.
Example 3.
www.digilentinc.com page 5 of 23
Copyright Digilent, Inc. All rights reserved. Other product and company names mentioned may be trademarks of their respective owners.
Properties are key-value pairs. The value of a property can either be a character string (e.g. the value
for compatible property), or a list of either decimal or hexadecimal numbers (e.g. the value of reg
property).
Each node requires a compatible property. A compatibility string will be assigned to that property.
You can use it to match device drivers with devices defined in the device tree. In Example 3, the
compatible property for device node leds is set to string “gpio-leds”, which indicates the
gpio-leds driver will be used for the device.
Usually, the device node name includes the base address of the device. However, the kernel actually
obtains the physical address of device registers via the reg property. The value of the reg property
contains a list of paired numbers separated by commas. Each pair begins with the base address of
the device, followed by the size of the register space. The corresponding kernel driver can usually
obtain the physical memory address with the function platform_get_resource and map the
physical memory into kernel virtual memory space by functions such as ioremap.
If your device has interrupt functionality, you must specify the interrupt number in the interrupt
property and set the interrupt-parent property to the phandler of the interrupt controller. You can
obtain the phandler of the interrupt controller with &(name field of interrupt controller).
For more in depth information on using the Zynq AP SoC interrupt controller with a device tree, see
Documentation/devicetree/bindings/arm/gic.txt within the kernel source.
OLED DTS Node: An Example
We abstract the following codes from the ZedBoard default device tree.1
Example 4.
1
http://www.digilentinc.com/zedboard
www.digilentinc.com page 6 of 23
Copyright Digilent, Inc. All rights reserved. Other product and company names mentioned may be trademarks of their respective owners.
Using Zynq with Linux
OLED
VBAT
VDD
RES
D/C
SCLK
SDIN
GPIO
55
56
57
58
59
60
Figure 2. OLED Hardware Connection
In Example 4, two devices are declared: the GPIO controller for Processing System of ZYNQ,
gpiops, and the on-board OLED display, zed_oled.
The device tree names the node for the GPIO controller gpiops, with the generic name of gpio and
a base address starting from 0xe000a000, according to conventional naming of the node. The full
name of gpiops is gpio@e000a000, as shown in the /sys file system and /proc file system. The
compatibility string of the GPIO controller is xlnx,ps7-gpio-1.00.a. The device will use the
xlnx-gpiops driver by matching the compatibility string of the node with that defined in the driver
source code. The reg property defines the gpiops GPIO controller by a physical address that begins
from 0xe000a000 with a size of 0x1000 (64KB). The interrupt is connected to the global interrupt
controller gic, as the phandler of gic (&gic in the DTS) passes to the interrupt-parent
property.
The second node shown in Example 4 is a device
with full name zed_oled. It is for the on-board
OLED device on the ZedBoard. In the hardware
design, the OLED is connected directly to the
gpiops GPIO controller (pin 55 to pin 60), as
shown in Figure 2. So, you can implement the driver
of the on-board OLED for the ZedBoard by getting
the GPIO pin number from the zed_oled device
node and toggling the corresponding GPIO pins
according to the OLED display transmission
protocol. As a result, the device zed_oled is not
actually a device controller with a physical register
space mapped in memory space, but a virtual device defined so that the driver in the kernel knows
which GPIO pins are used. So, there is no base address, no register space, no @<base address>
part in the full name of the device nodes, and no reg properties in the device tree. The device does
have a compatibility string so that the corresponding pmodoled-gpio driver can be registered for the
device and toggle the GPIO pins to control the OLED display. There are also several properties that
specify which GPIO pins to use.1
Device Tree Compilation
The DTS file needs to be compiled into a DTB file that the kernel can understand. The device tree
compiler (DTC), located under scripts/dtc in the Linux kernel source, will compile the DTS file into
a DTB file with the command: