Digilent Embedded Linux User Manual

Embedded Linux Development Guide
Revision: January 14, 2013
1300 NE Henley Court, Suite 3
(509) 334 6306 Voice | (509) 334 6300 Fax
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
GIC Snoop 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.
Using Zynq with Linux
/dts-v1/;
/ { model = "Xilinx Zynq ZED"; compatible = "xlnx,zynq-zed"; #address-cells = <0x1>; #size-cells = <0x1>; interrupt-parent = <&gic>;
ps7_ddr_0: memory@0 { device_type = "memory"; reg = <0x00000000 0x20000000>; }; ... ps7_axi_interconnect_0: axi@0 { #address-cells = <1>; #size-cells = <1>; compatible = "xlnx,ps7-axi-interconnect-1.00.a", "simple-bus"; ranges ;
gic: intc@f8f01000 { interrupt-controller; compatible = "arm,cortex-a9-gic"; #interrupt-cells = <3>; reg = < 0xf8f01000 0x1000 >, < 0xf8f00100 0x0100 >; }; ...
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.
Using Zynq with Linux
leds { compatible = "gpio-leds";
mmc_led { label = "mmc_led"; gpios = <&gpiops 7 0>; linux,default-trigger = "mmc0"; }; };
(Name) : (Generic Name)@(Base Address) { compatible: (compatibility string); reg: < (base address) (size) >; interrupt-parents: < (interrupt controller phandle) >; interrupts: < >; (param1): (string value); (param2): < (number value, decimal or hexical) >; };
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.
Using Zynq with Linux
gpiops: gpio@e000a000 { compatible = "xlnx,ps7-gpio-1.00.a"; #gpio-cells = <2>; reg = <0xe000a000 0x1000>; interrupts = <0x0 0x14 0x0>; interrupt-parent = <&gic>; gpio-controller; };
zed_oled { compatible = "dglnt,pmodoled-gpio"; /* GPIO Pins */ vbat-gpio = <&gpiops 55 0>; vdd-gpio = <&gpiops 56 0>; res-gpio = <&gpiops 57 0>; dc-gpio = <&gpiops 58 0>; /* SPI-GPIOs */ spi-bus-num = <2>; spi-sclk-gpio = <&gpiops 59 0>; spi-sdin-gpio = <&gpiops 60 0>;
};
Properties
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:
$ ./scripts/dtc/dtc -I dts -O dtb -o devicetree.dtb digilent_zed.dts
The DTC compiler can also de-compile a DTB file back to the DTS file with the command:
$ ./scripts/dtc/dtc -I dtb -O dts -o digilent_zed.dts devicetree.dtb
You can view other options for the DTC compiler with the -h option:
1
Structure gpio-specifier is passed to the properties (e.g. vbat-gpio = <&gpiops 55 0>). Refer to
Documentation/devicetree/bindings/gpio/gpio.txt for more details.
www.digilentinc.com page 7 of 23
Copyright Digilent, Inc. All rights reserved. Other product and company names mentioned may be trademarks of their respective owners.
Loading...
+ 16 hidden pages