Embedded Linux Tutorial - Zybo
by Commanderfranz in Circuits > Linux
129894 Views, 60 Favorites, 0 Comments
Embedded Linux Tutorial - Zybo
This Embedded Linux hands-on tutorial for the Zybo will provide step-by-step instructions for customizing your hardware, compiling the Linux Kernel and writing driver and user applications. This documentation intends to integrate knowledge and skills in FPGA logic circuit design, standalone software programming, and Linux operating system and software development, and apply them to the Zybo.
In this tutorial, we will start from the Zybo Base System Design (available on the Zybo product page of the Digilent website). The system architecture for the Zybo Base System Design is shown in the first picture in this step.
In the Zybo Base System Design, we connect UART1 to USB-UART, SD0 to the SD Card Slot, USB0 to the USB-OTG port, Enet0 to the Giga-bit Ethernet Port, and Quad SPI to the on-board QSPI Flash. These cores are hard IPs inside the Processing System (PS) and connect to on-board peripherals via Multiplexed I/O (MIO) pins. The use of PS GPIO is is connected to BTNs 4 and 5. In the Programmable Logic (PL), we have an HDMI Tx Controller, VDMA, and GPIO IP cores to talk to the ADV7511 HDMI Transmitter Chip and I2S and GPIO IP Cores for ADAU1761 Audio Codec. More details of the hardware design can be found in the documentation inside the Zybo Base System Design package.
Before going through this tutorial, we recommend that you read Getting Started with Embedded Linux -- ZedBoard first. You can follow this tutorial with the Embedded Linux Development Guide (available on the Digilent Website Embedded Linux Page). The guide will provide you with the knowledge you may need in each step of the development.
In this tutorial, we are going to use Vivado 2014.1 Webpack in a Linux environment. All the screen shots and codes are done using Vivado Design Suite2014.1 in Fedora 19 x86_64.
Required Materials:
- U-boot*
- Pre-built File System Image (available in the Zybo Linux Reference Design)
*Note: Use the Master-Next Branches until further notice
That’s it for the background information on this tutorial, now it’s time to get our hands dirty with some real design!
Download Base System
Download the Zybo Base System Design from the website and unzip it into our working directory (our working directory is named tutorial throughout this tutorial). For more information on the hardware design, please refer to Project Guide under doc folder.
Open the Base System Design
Source Vivado 2014.1 settings and open the design with Vivado Design Suite (vivado). You will see the Vivado window pop up.
Note: There are four settings files available in the Vivado toolset: settings64.sh for use on 64-bit machines with bash; settings32.sh for use on 32-bit machines with bash; settings32.csh for use on 32-bit machines with C Shell; and settings64.csh for use on 64-bit machines with C Shell.
Delete Existing LED Core
We are going to detach LEDs from the GPIO core in the PS first. So, we need to click on the IP integrator and open the Block Diagram as shown in the first image in this step. Then we need to delete the current LED IP as shown in the second image. We will handle the modification of external pin location configuration (xdc file) in later steps.
Note: In Figure 4 there is a Yellow bar indicating the need for an upgrade. To upgrade hit show IP status, make sure all are selected and hit Upgrade Selected.
Name Vendor
Before we can start implementing our myLed IP Core we need to name the Vendor that will automatically be applied in the IP packager. In Vivado 2014.1 this is not automatically done for you. To do this first go to the Project Settings under Project Manager on the left side of the window (image 1) and the project settings window will pop up. In the Project Settings Window select IP (image 2). Notice that the vendor is chosen as (none), this will cause a Vivado Internal Exception. You can name the Vendor whatever you like (image 3).
Create MyLed IP
Now we can start implementing our myLed IP Core. Click Tools -> Create and Package IP… from the menu (image 1). The Create and Package New IP window will pop up (image 2), Click Next. In the next window name the new IP and click next again (image 3).
Add Interfaces
The next window will be the Add Interfaces Window. This will create the AX14 Interface for the myLed peripheral. Make sure the interface type is Lite, the mode is Slave, the data width is 32 bits and the number of registers is 4. Change the Name to S_AXI rather than S00_AXI. We only need 1 register but the minimum we can select is 4. Then click next.
Edit IP
The next window will prompt for the next steps to finish creating the IP. Change the Radio button to select Edit IP and Hit finish. We need to add user logic to the IP so that our slave is connected to the LED output.
After selecting finish the Create and Package IP window will disappear and the next window you will see is the edit_myLed window. This is where we will add our user logic.
MyLed_v1_0_S_AXI
In the Project Manager, click the circle next to myLed_v1_0 and highlight myLed_v1_0_S_AXI (image 1). This contains the user logic inside of the myLed IP. We need to add two lines of code to complete the user logic for this module. First we need to create a user port which called led (image 2). Next we need to connect the internal slave to this user port. We will connect slv_reg0[3:0] as we have four LEDs (image 3).
MyLed_v_0
Next we need to connect the user logic to myLed. In the project manager select the file myLed_v_0. To complete the IP there are two lines of code we need to add to this file. Under the comment that says Users to add ports here, add a port for the LEDs (image 1). Connect the led output from the previous file containing the user logic to myLed (image 2).
Package IP
Now that our IP is created and the User Logic is defined, we need to package our IP. Under Project Manager on the left side of the window select Package IP. A new tab will open that is called Package IP. On the left side of this tap there are a series of labels. We need to complete those that do not have green check marks.
First select IP customization Parameters. At the top of that window select the option to Merge changes from IP Customization Parameters Wizard.
Ports and Interfaces
Next select the IP Ports and Interfaces. Notice that your new LED IP is there.
IP GUI Customization
Next Select IP GUI Customization. Our IP GUI is fine as is so we won’t make any changes here.
Now we can Review and Package our myLed IP. Select Review and Package IP and press the Re-Package IP button. Our IP is now completed and packaged.
Add MyLed IP
We are going to add our IP to our design. Right-click anywhere on the block design and Click Add IP (image 1). Select the correct IP, myLed_v1.0, and press enter (image 2).
Run Connection Automation
The AXI4-Lite bus of myLed IP Core needs to be connected to the processing system. At the top of the window click the blue text that says Run connection automation. This will connect the inputs of the myLed IP core. You should see that S_AXI is now connected to the first output of the AXI Interconnect.
Create LED Port
Next we need to connect the myLed IP to an external port. The myLed IP core that we implemented will not connect to the existing LEDs_4Bits port so we need to make a new external port called led. Click on the existing LED port and press delete. To create the new port right click and select create port. Name the port, select output, select vector [3:0] and press enter.
Connect LED Port
Next connect the led port to the myLed IP by clicking on the port and dragging a connection to myLed .
Modify XDC
The final step is to specify the pin numbers for myled_0_LED_pin to physically connect our customized IP core to the on-board LEDs. In the Project Manager expand the Constraints section and select the base.xdc file (image 1). Within that file change the names of the external LED pins so that they match the name of our external led port (image 2).
Generate Bitstream
Regenerate the bitstream for the hardware design by clicking on Generate Bitstream under Program and Debug on the left side of the window.
U-Boot Source Code
*Note: Use the Master-Next Branches until further notice
Get the source code for U-Boot from the Digilent git repository. There are two ways to retrieve the source code:
Using git command:
If you have git installed in your distribution, you can clone the repository to your computer by command git clone https://github.com/Digilent/u-boot-Digilent-Dev.g... The whole Git Repository is around 55MB, as shown in image 1. If you want to get a separate branch, for example the next branch follow image 2. The next contains the u-boot that is not yet released. The clone url referenced above can be found on the Digilent git-hub page as seen in image 3.
Download a compressed package:
If you only want to use u-boot once and do not want to track the updates, you can also download a compressed package from github.com: https://github.com/Digilent/u-boot-digilent. Go to the drop down box that shows the branch and select tags. The most recent tag is zynq-beta-v2.2. (image 4).
If you downloaded the tar.gz, you can decompress it using command
tar zxvf u-boot-digilent-2012.04-digilent-13.01.tar.gz
If you downloaded the zip file, you can decompress it using command
unzip u-boot-digilent-2012.04-digilent-13.01.zip
Compile U-Boot
To compile U-Boot, we need cross-compile tools which are provided by Vivado 2014.1. Those tools have a prefix arm-xilinx-linux-gnueabi- to the standard names for the GCC tool chain. The prefix references the platforms that are used. The Zybo board has two arm cores so we reference arm. In order to use the cross-platform compilers, please make sure Vivado 2014.1 settings have been sourced. If not, please refer to step 2. To configure and build U-Boot for Zybo, follow the image attached to this step.
U-boot.elf
After the compilation,
the ELF (Executable and Linkable File) generated is named u-boot. We need to add a .elf extension to the file name so that Xilinx SDK can read the file layout and generate BOOT.BIN. In this tutorial, we are going to move the u-boot.elf to sd_image folder and substitute the u-boot.elf that comes along with Zybo Base System Design Package.
Export Hardware for SDK
Export the hardware design (after step I-16) to Xilinx SDK by clicking on File -> Export -> Export Hardware for SDK…, as shown in the first image.
Leave the workspace as . Make sure that Launch SDK is checked and click OK, as shown in the second image.
Note: You may have to export twice.
New Project
After SDK launches, the hardware platform project is already present in Project Explorer on the left of the SDK main window, as shown in image 1. We now need to create a First Stage Bootloader (FSBL). Click File->New->Project…, as shown in image 2.
Application Project
In the New Project window, select Xilinx->Application Project, and then Click Next.
Name the Project FSBL
We will name the project FSBL. Select hw_platform_0 for Target Hardware because it is the hardware project we just exported. Select standalone for OS Platform. Click Next.
Create Zynq FSBL Template
Select Zynq FSBL as template, and click Finish.
FSBL Hook
For the Zybo, we need set the mac address for the Ethernet in the fsbl hook. We want the mac address for the Ethernet to remain constant when we turn off and on the Zybo Board. You can swap the fsbl_hooks.c file in the FSBL project with the fsbl_hooks.c under source/vivado/SDK/fsbl in the Zybo Base System Design.
After you have saved the changes to fsbl_hooks.c,
the project will rebuild itself automatically. If it does not rebuild, Click Project->Clean to clean the project files, and Project->Build All to rebuild all the projects. The compiled ELF file is located in zybo_base_system/source/vivado/hw/zybo_bsd.sdk/SDK/SDK_Export/FSBL/Debug
Create Boot Image
Now, we have all the files ready to create BOOT.BIN. Click Xilinx Tools -> Create Zynq Boot Image.
Add FSBL, System.bit and U-boot.elf
In the Create Zynq Boot Image window, Click Browse to set the path for FSBL elf. Click Add to add the system.bit file found at /zybo_base_system/source/vivado/hw/zybo_bsd/zybo_bsd.sdk/SDK/SDK_Export/hw_platform_0/.Click Add to add the u-boot.elf file found at zybo_base_system/sd_image/. It is very important that the 3 files are added in this order, or else the FSBL will not work properly. It is also very important that you set FSBL.elf as the bootloader and system.bit and u-boot.elf as data files. In this tutorial, the sd_image folder is set as output folder for the BIN file. Click Create Image.
Linux Kernel Source Code
*Note: Use the Master-Next Branches until further notice
Get the Linux kernel source code from Digilent git repository. There are two ways to retrieve the source code:
Using git command: If you have git installed in your distribution, you can clone the repository to your computer by command git clone https://github.com/DigilentInc/Linux-Digilent-Dev... The whole Git Repository is around 850MB, as shown in image 1.
Download a compressed package: If you only want to use u-boot once and do not want to track the updates, you can also download a compressed package from github.com: https://github.com/DigilentInc/Linux-Digilent-Dev. Click Tags on the top right corner of the page.The most recent tag is zynq-dt-for-3.14 (image 2).
If you downloaded the tar.gz, you can decompress it using command
tar zxvf linux-digilent-v3.6-digilent-13.01.tar.gz
If you downloaded the zip file, you can decompress it using command
unzip linux-digilent-v3.6-digilent-13.01.zip
Configure the Kernel
We will start to configure the kernel with the default configuration for Zybo. The configuration is located at arch/arm/configs/xylinx_zynq_defconfig. To use the default configuration follow the image attached to this step.
Compile the Linux Kernel
Follow the example in the image.
Make Uimage
After the compilation, the kernel image is located at arch/arm/boot/zImage. However in this case the kernel image has to be a uimage (unzipped) rather than a zimage. To make the uimage follow the image in this step.
Optional Path Change
Note: Depending on your distribution of linux you may get an error regarding the path of the mkimage. If this is the case you can change the path following the image in this step.
Make Uramdisk
To boot the Linux Operating System on the Zybo, you need BOOT.BIN, a Linux kernel image (uImage), a device tree blob (DTB file), and a file system. BOOT.BIN has been created in Section III and uImage has been compiled in Section IV. We will now compile the DTB file. The default device tree source file is located in the Linux Kernel source at arch/arm/boot/dts/zynq-zybo.dts.
RAMDISK: For zynq only the ramdisk image has to be wrapped in a u-boot header in order for u-boot to boot with it. This is shown in the image in this step.
Generate DTB File
Follow the example provided in the image.
Copy File Image to SD Card
RAMDISK) Copy BOOT.BIN, devicetree.dtb, uImage and uramdisk.image.gz to the first partition of an SD card, as shown in the first image – RamDisk.
NOTE: The first partition of the SD card is mounted to /media/ZYBO_BOOT
Boot From SD Card
Plug the SD Card into the Zybo. To boot from SD card, jumper 7 needs to be configured for USB as shown on the Zybo Board and Jumper 5 must be connected to SD. Connect UART port to PC with micro USB cable and set the UART terminal on PC to 115200 baud rate, 8 data bits, 1 stop bit, no parity, and no flow control. After powering on the board, the console should be seen at the UART terminal if you use RamDisk. More information about this file system can be found in Getting Started with Embedded Linux ZedBoard.
Create a Drivers Directory
Create a directory named drivers in the Tutorial folder, as shown the image in this step. Inside the drivers directory, we will compose the driver for the myLed controller.
Create the Makefile
We need a Makefile so that we can compile the driver. The Makefile is created in image 1.
After creating the file, hit I to change to insert mode and insert the following text in image 2. Make sure you use tab characters where appropriate.
Create Myled.c
We will start with a simple driver that creates a file named myled under the Linux /proc file system. The status of the on-board LEDs can be changed by writing a number to the file. The driver is coded in the last four images and is attached
Downloads
Compile Driver
Compile and generate the driver module using make. Don’t forget to source Vivado settings.
Add Myled to the Device Tree
We need to add the myLed device node into the device tree.
Make a copy of the default device tree source in the drivers folder, and modify it according to the second image. The compatibility string of the node is the same as we define in the driver source code (myled.c: line 182). The reg property defines the physical address and size of the node. The address here should match with the address of the myLed IP core in the address editor tab of the Vivado design, as shown in the last image.
Recompile Device Tree Blob
Recompile the device tree blob as shown in the attached image.
Copy Driver and Modified Device Tree to SD Card
Copy these two files to the first partition of the SD card, as shown in the image in this step. We are ready to test our driver on-board now.
Boot From SD Card
Plug the SD card into the Zybo, and we can start testing our driver. Use the insmod command to install the driver module into the kernel. After the driver is installed, an entry named myled will be created under the /proc file system. Writing 0x0F to /proc/myled will light up LED 0~3. You can either remove the driver with command rmmod or power off the system by command poweroff. In both case, all the LEDs will be turned off, as shown in Figure 69 and 70. For instructions on using the terminal with the Zybo. please refer to Step V-4 or Section Boot from SD in Getting Started with Embedded Linux – ZedBoard.
User Application: Led_blink
In this section, we will write a user application that makes the LEDs
blink by writing to /proc/myled. Create a directory named user_app in the Tutorial folder, as shown in the first image. Inside the user_app directory, we will compose the led_blink.c, as shown in the second and third image.
Create Makefile and Compile Led_blink
Compose a Makefile and compile led_blink.c into led_blink.o, as shown in the three images in this step.
Insert the SD card into the computer, and copy the binary file led_blink onto the first partition of SD card.
Run Led_blink
Plug the SD card into the ZYBO. Use the insmod command to install the driver module into the kernel. Run led_blink and the LED will start blinking.
Feedback!
Just a reminder, this is a draft. There will be an official copy that will be released on Digilentinc.com.
I appreciate any feedback to make the official copy stronger.