Building PetaLinux for the UltraZed & PCIe Carrier Card

By Adam Taylor

In this installment of our exploration of Avnet’s UltraZed SoM and the PCIe carrier card, we will develop an example application. We will start by getting both components up and running, utilize the Xilinx Vivado Design Suite to create a hardware platform, and then develop a PetaLinux image that will enable us to leverage the power of the UltraZed SoM.

Our solution requires the implementation of both hardware and software elements. The hardware solution defines both the configuration of the processing system (PS) and programmable logic (PL) design. If the application runs on the A53 based Application Processing Unit (APU), the software solution for the UltraZed PS can be implemented using either a bare metal, FreeRTOS or Linux approach. If the application runs on the R5 within the Realtime Processing Unit (RPU), our options are either bare metal or FreeRTOS.

Many of the applications in which the PCIe carrier card may be utilized require complex software capabilities for networking, communication or processing using high-level, open source libraries and frameworks. With this in mind, our example design will demonstrate how to deploy Linux on the APU by outlining the PetaLinux development flow.

To get our project started, we must first install the UltraZed PCIe carrier card board definition into Vivado. Installing these files makes Vivado aware not only of the UltraZed SoM configurations e.g. DDR memory settings, but also the interfaces on the PCIe carrier board. We can download the board definitions from ultrazed.com. These should then be installed into the Vivado installation path under \\data\boards.

Once the board definition files are installed, we can create a new project by selecting the PCIe carrier card.

default part screen

For this example application, we will create a simple block design which connects the LEDs and switches on the PCIe carrier card to the PS using AXI GPIO in the PL. This allows us to demonstrate how we can use Linux to communicate between the APU and peripherals in the PL. Before adding in the AXI GPIO, we must first create a block design, then add the Xilinx® Zynq® UltraScale+™ MPSoC processing system.

 

block design

With the Zynq PS added, we can now run the block automation, which will configure the MPSoC processing system for the UltraZed. Next, we add in the GPIO by simply dragging and dropping the desired interface from the board tab onto the block diagram. This will add the AXI GPIO elements and map the IO to the design. At this point, all we need to do is run the connection automation to implement the AXI interconnections between the AXI GPIO and the Zynq PS.

 

Zync PS

When the block automation completes, the bitstream can be generated and exported, allowing the creation of the PetaLinux project to generate the Linux OS.

To create the Linux OS deployed on the PS APU, we will use the PetaLinux tools suite. PetaLinux enables us to customize the Linux Kernel, File System, Second Stage Boot Loader and Platform Management Unit firmware. But, to utilize PetaLinux, we need a Linux development environment. For this example, I have used a virtual machine to create this development environment.

To build our Linux image using PetaLinux, we will issue the following commands:

  1. Create a PetaLinux project using the command: petalinux-create --type project --template zynqMP --name <project name>
  2. Import the hardware definition created in Vivado: petalinux-config --get-hw-description= <path-to-vivado-hardware-description-file or DSA>
  3. If you want to make application specific changes to the kernel, rootfs etc. you can configure the PetaLinux build using the commands: petalinux-config -c <kernel, u-boot, PMUFM, device-tree or rootfs>
  4. Once all customizations are completed, build the PetaLinux image using the command: petalinux-build Package the petalinux application such that we have a Linux image and a boot.bin to transfer to the boot memory: petalinux-package --boot --fsbl zynqmp_fsbl.elf --u-boot u-boot.elf --pmufw pmufw.elf –fpga fpga.bit

Following completion of the packaging, the Linux image (image.ub) should be processed and the boot.bin file can be copied onto the selected boot medium. The OS can now be booted.

Petalinux boot screen

With Linux OS up and running on the UltraZed, all we need to do now is create our application to drive the LEDs on the PCIe carrier card.

Creating a Linux application is a little more in depth than creating a bare metal or FreeRTOS application. As such, it is important to understand a little about how Linux is structured, particularly the split between kernel space and user space.

The Linux operating system itself is split into two distinct areas: kernel space and user space. The kernel space has higher privileges and is typically where the Linux device drivers reside for both PS and PL peripherals. User space applications cannot directly access device drivers in the kernel space. To access device drivers, a user space application must therefore make system calls into the kernel space to gain access to the drivers.

In Linux, these drivers typically fall into one of several types:

  • Network devices such as Ethernet
  • Block memory storage devices like eMMC and USB
  • Character devices which include many other device interfaces e.g. AXI GPIO
  • MTD devices, i.e. flash memory
  • Platform framework, i.e. V4L

For our Linux deployment, we will be working in the user space. We can access these devices in the kernel space using a virtual file system. For many devices, this allows our application to interact with the driver in a similar manner to working with a standard file e.g. open, close, read and write.

memory diagram

When we work with the virtual file system, we can determine the buses, devices and classes available for use in our Linux application under the following directories:

  • /sys/bus – list of buses in the system
  • /sys/devices – list of devices in the system
  • /sys/class – list of classes in the system, enumerated devices by class e.g. net, input, block

To get this simple LED example up and running, we need to know the registration of the AXI GPIO. This will enable us to interact with the AXI GPIO using the virtual file system.

To determine the registration of the AXI GPIO, we can issue the command dmeg | grep_gpio from within the sys/class directory. This will provide the registration of the different GPIO elements as shown below.

  • Channel 1 of AXI GPIO 0 is registered at 504, the 8 LEDs are addressed as 504 to 511
  • Channel 2 of AXI GPIO 0 is registered at 496, the 8 DIP are addressed as 496 to 503
  • Channel 1 of AXI GPIO 1 is registered at 493, the push buttons are addressed as 493 to 495

AXI GPIO registration

With the registration of the Pl AXI GPIO elements within the Linux OS now known, we can create our Linux application. For this example, I created the application using the Xilinx SDK, then transferred the ELF file to the PCIe Carrier card using Ethernet and the WinSCP program.

Linux application creation

The application I have chosen to demonstrate here is simple. It flashes the most and least significant LEDs once a second. To enable this functioning, the SW performs the following:

  1. Open the GPIO for exporting open("/sys/class/gpio/export", O_WRONLY);
  2. Export both the MSB and LSB e.g. elements 504 and 511 write(exportfd, "504", 4);
  3. Set the direction of the GPIO to output open("/sys/class/gpio/gpio504/direction", O_RDWR);
  4. Get the value of the GPIO read for updating open("/sys/class/gpio/gpio504/value", O_RDWR);
  5. Implement the main loop which changes the values once a second write(valuefd, "1", 2); write(valuefd2,"1", 2);

Once uploaded and executed on the UltraZed and PCIe Carrier card, you will notice the application running and the LED state toggling once a second. If you do not see the LED flashing a common error, check to make sure you have exported the correct GPIO.

If you have followed along with our example, you should now understand the development flow and how to create the Vivado hardware, Linux operating system and Linux application. From here, you can update the design as required to address any value-added needs using the UltraZed and PCIe Carrier card.

Over the two parts of this introduction to the AVNET UltraZed SOM and Carrier card, I have outlined the benefits developer gain from using a SoM based approach. These benefits include an accelerated development time and risk reduced development. These articles have also demonstrated how quick and easy it is get a Linux application up and running by accessing elements of the design contained within the PL.

Of course, the beauty of starting the development with a SoM and carrier card is it provides flexibility for both application and product road map development.

All files for this example can be found on my GitHub.

Read also: Working with the UltraZed SoM & PCIe Carrier Card

This post was sponsored by Avnet.

By Adam Taylor

Adam Taylor is a Chartered Engineer and Fellow of the Institute of Engineering and Technology. He is the author of the very popular MicroZed Chronicles based on using the Xilinx Zynq SoC.

RELATED ARTICLES

Working with the UltraZed SoM & PCIe Carrier Card

I recently had the opportunity to evaluate the UltraZed ™ System on Module (SoM) and accompanying PC...

3 ways All Programmable SoCs create new opportunities for designers

Usually, two heads are better than one. Yet sometimes, they introduce conflicting perspectives and p...

Spending on design up front can save you from long-term pain

Many creators prioritize speed to market above all else, believing in the famous adage from movie Fi...