Petalinux is the Xilinx’s toolchain used for creating whole embedded Linux system for Xilinx devices. It is a convenient way of building all blocks necessary to create the bootable image for the targeted platform. But lets go to the very beginning. What you need for using the Petalinux toolchain except the Development board? Well basically one has to create “a preferably virtual OS – VirtualBox or Vmware player” with the OS recommended via the UG1144. I have been using the Kubuntu 18.04 LTS and it works very good with the latest Petalinux Version (2019.1). You may think at first, that choosing a newer version would be fine, but! Never use the most up to date version of the guest Linux system (Such as Suse Thumbleweed)! This will save you plenty of time debugging the Petalinux errors. Especially fixing python errors is awesome (Or errors with deprecated functions and libraries). Go for the latest only if you are masochist smile

The recommended flow is to open up Vivado and create a default project with the targeted board (Note that if you are using non-Xilinx dev. board, you need to download the Vivado Board files from the manufacturer and put them inside /Vivado/2019.1/data/boards/board_files (Or adjust the location in vivado settings) so that they should be visible from Vivado GUI). Once the project is created, you can either customize the project yourself (For beginners, starters and people trying to bring up a board for the first time: Make the project as simple as possible without any unnecessary components! – This is going to save you a lot of time – Create basically only a singe block design with only the ZYNQ / ZYNQMP processing IP. Nothing more!). Once in the Block Designer : Run block Automation. This  will basically configure the ZYNQ/ZYNQMP IP based on the board specification file. After this, you have to synthesize the Out-Of Context runs for the Block Designer and Export Hardware Definition File (HDF) via the Vivado’s menu toolbar. You can optionally generate a bitstream for the targeted device and include it in the .HDF file.

  • Tip: The HDF file contains the hardware specification and optionally a bitstream. Although its extension is .hdf, you can change it to .zip, extract it and see what’s really inside. Even though its not required to include the bitstream, I suggest that you always do so as I have already seen some errors with missing bit files.
  • Tip: The HDF file cannot be generated if there is no Zynq / ZynqMP Processing system IP inside a Block Designer. This .bd file needs to be somewhere in the hierarchy under your Vivado TOP-level module.

Some vendors and Xilinx Itself provide the BSP (Board Support Package) files. My recommendation is not to use them, as they provide some pre-configured system and you are not usually aware of how it has been configured. Instead create a new Petalinux project and configure it according to the HDF file generated by Vivado. Very important thing is to never mix the Vivado/XSDK/Petalinux versions. Always maintain a single version toolset such as 2019.1. This will as well ease your pain during building. The best way to create the HDF file is to target the Vivado project for a development board (Such as ZCU102/ZCU104 … ) and configure the Zynq UltraScale+ MPSoC Processing System IP according to the target board via “run block automation” option inside the Vivado’s block designer. I do personally recommend to double-check the PS-DDR memory controller configuration as vendors do occasionally change shipped SODIMM modules and or DDR ram chips, which may lead to blank console UART output of the board during boot, as nothing will likely work. 

Petalinux Installation and Configuration

Recommended package setup for installing Petalinux 2019.1 on Kubuntu 18.04LTS (you don’t need tftp):

sudo apt-get update
sudo apt-get install tofrodos iproute2 gawk make net-tools libncurses5-dev libssl-dev
sudo apt-get install flex bison libselinux1 wget diffstat chrpath socat xterm
sudo apt-get install autoconf git libtool unzip texinfo zlib1g-dev gcc-multilib
sudo apt-get install build-essential screen pax gzip tar zlib1g:i386

Installing Petalinux:

chmod +x /petalinux-v2019.1-final-installer.run               # Allow installer to be executed
 ./petalinux-v2019.1-final-installer.run /Xilinx/Petalinux    # Install to target Directory

After installing source the Petalinux Environment:

nano ~/.bashrc

Add line (If it fits for you):
source /Xilinx/Petalinux/settings.sh         # Environment for Petalinux
source /Xilinx/Vivado/VERSION/settings64.eh  # Environment for Vivado
source /Xilinx/SDK/VERSION/settings64.sh     # Environment for XSDK

export PATH="$PATH:/XILINX/dtc"               # Includes the DeviceTreeCompiler in PATH
export PATH="$PATH:/XILINX/u-boot-xlnx/tools" # Includes the mkimage in the PATH Variable

Also change shell to bash throught the console:

chsh -s /bin/bash
sudo cp /bin/sh /bin/sh.bac
sudo rm /bin/sh
sudo ln -s /bin/bash /bin/sh

Xilinx default git repositories in case you need them: (Likely only the dtc and device-tree sources are optionally required):

Useful Linux commands:

df -h                                       # Displays the filesystem usage
top(htop)                                   # Lists the processes running in linux and their resource usage
fdisk -l                                    # Lists available discs and partitions
find -name "*.bif"                          # Find Files inside a directory
devmem 0x8000000                            # Read data 32-bit at this physical address (Will hang if not accessible)
ifconfig eth0 "ipaddress" netmask "netmask" # Setups the interface with IP/mask

lsblk                                  # list information about block devices
mount /dev/mmcblk1p1 /mnt/             # mounts the device if it exist to /mnt/
umount /mnt                            # unmounts the device

tar -xvzf file.tar.gz -C /TargetDir/   # Untar file to target Location (--overwrite-dir)
cp -a /SourceDir/. /TargetDir/         # Copy all files within folder
rm -rfv /TargetFolder/                 # Remove all files from a given folder

###################################
# Bootable Linux Image manipulation
mkimage -f Image.its Image.ub          # Creates Bootable image for SD card from .its file description
mkimage -l image.ub:                   # Displays the content of image.ub
dumpimage -T flat_dt -p 0 -i image.ub Image         # Extract Linux kernel
dumpimage -T flat_dt -p 1 -i image.ub System.dtb    # Extract Linux DeviceTreeBlock
dumpimage -T flat_dt -p 2 -i image.ub ramdisk.cpio  # Extract InitRamFSuntitled:Untitled-1

# xilinx BootImage Manipulation:
bootgen -image boot.bif -o i boot.bin -arch zynqmp -w on

##########################
# Device Tree Manipulation
dtc -I dts -O dtb -o system.dtb system-top.dts # Compile .dts to .dtb
dtc -I dtb -O dts -o system-top.dts system.dtb # Decompile .dtb to dts

make nconfig     # Newever ncures version with better interface than menuconfig
make menuconfig  # Default menu configuration utility
make xconfig     # Grafical configuration interface

################################
# Petalinux toolchain commands:
petalinux-create --type project --template zynqMP --name ZynqMPX                                                 # Create new petalinux project
petalinux-config --get-hw-description=/PATHTOFOLDERWITHHDF                                                       # Configure project according to HDF
petalinux-config -c rootfs                                                                                       # Configure RootFileSystem Features
petalinux-config -c kernel                                                                                       # Configure Kernel Features
petalinux-config -c uboot                                                                                        # Configure U-Boot Features
petalinux-build                                                                                                  # Builds the Project
petalinux-package --force --boot --fsbl zynqmp_fsbl.elf --fpga system.bit --pmufw pmufw.elf --u-boot u-boot.elf  # Create boot.bin
petalinux-build -x mrproper                                                                                      # Cleans All generated files

##################################################
# Programming FPGA from petalinux via FPGA Manager: 
fpgautil -b /System.bit
ITS file Example

Example .its file specification (edit with text editor and save as .its):

/*************************************************************************
 * U-Boot uImage source file with multiple kernels, ramdisks and FDT blobs
 *************************************************************************/

/dts-v1/;

/ {
    description = "Various kernels, ramdisks and FDT blobs";
    #address-cells = <1>;

    images {
        kernel@0 {
            description = "Linux Kernel";
            data = /incbin/("/PATH_TO_KERNEL_IMAGE/Image");
            type = "kernel";
            arch = "arm64";
            os = "linux";
            compression = "none";
            load = <0x80000>;
            entry = <0x80000>;

        };
        
        fdt@0 {
            description = "devicetree";
            data = /incbin/("/PATH_TO_DEVICE_TREE_BLOB/system.dtb");
            type = "flat_dt";
            arch = "arm64";
            compression = "none";

        };

        // Note: Comment out ramdisk if the initial FS resides for example on partition 2 of the bootable SD.
        ramdisk@0 {
            description = "ramdisk";
            data = /incbin/("/PATH_TO_INITRAMFS/rootfs.cpio.gz");
            type = "ramdisk";
            arch = "arm64";
            os = "linux";
            compression = "none";
        
        };

    };

    configurations {
        default = "config@1";

        config@1 {
            description = "Ultrascale Configuration";
            kernel = "kernel@0";
            fdt = "fdt@0";
            ramdisk = "ramdisk@0";
            
        };
    };
};
BootImage Specification

Bootimage specification (Edit with text editor and save as .bif):

MyBootImage:
{
  [fsbl_config] a53_x64
  [bootloader,destination_cpu=a53-0] zynqmp_fsbl.elf                  // First Stage Bootloader
  [pmufw_image] pmufw.elf                                             // Platform management Unit
  //[destination_device=pl] system.bit                                // Optional bitstream 
  [destination_cpu=a53-0,exception_level=el-3,trustzone] bl31.elf     // Arm Trusted Firmware
  [destination_cpu=a53-0,exception_level=el-2] u-boot.elf             // u-boot
}

Tip: you can download a full-featured RootFile System for the following distributions as well:

Or Create your own root-file system from: https://busybox.net

Tip: In order to include nano editor in the rootfs, open: … /project-spec/meta-user/recipes-core/images/petalinux-image-full.bbappend and add: IMAGE_INSTALL_append = ” nano”. Once this is done, the package should be visible under petalinux-config -c rootfs -> user packages.

Creating SD card from scratch
WARNING: Change /dev/sdb according to your setup!

sudo dd if=/dev/zero of=/dev/sdb bs=1024 count=1      # Erase first few bytes on the SD (partition Info)
sudo fdisk -l /dev/sdb                                # View SD Card info: 15931539456 bytes -> Compute new amount of cylinders as SIZE(bytes)/8225280 = 1936.89... use 1936
sudo fdisk /dev/sdb                                   # Launch Disc Manipulation Utility on the SDCard Device

Run Commands:
x     # Go to expert mode
h     # Set num of heads to 255
255   # Set num of heads to 255
s     # Set num of sectors 63
63    # Set num of sectors 63
c     # Set num of cylinders 1936 (Should be defaulted to the highest value anyway)
1936  # Set num of cylinders 1936
r     # Return from Expert mode

n      # New Partition
p      # Make Primary
1      # partition number
2048   # use default value for first sectors
+1024M # last Sector 1GB after to create a partition of 1GB

n        # New Partition
p        # Make Primary as well
2        # partition number
411648   # First sector - Use default value
15759359 # Last Sector - Use Default Value

# Add Boot Flag for FAT32 Boot partition
a  # Add Boot Flag to the First partition
1  # Choose the First Partition

t  # Change Filesystem of the first partition to FAT32
1  # Choose the First Partition
c  # Code for FAT32

t  # Change Filesystem of the second partition (Should be defaulted to linux anyway)
2  # Choose the Second Partition
83 # Code for Linux Filesystem

p (Visually Check the SD card configuration)
w (write the previously configured partitions onto the SD card)

# Format the partitions according to their filesystems:
sudo mkfs.vfat -F 32 -n boot /dev/sdb1
sudo mkfs.ext4 -L root /dev/sdb2
Petalinux DeviceTreeCustomization

Recommended via “system-user.dtsi” inside: PROJECT/project-spec/meta-user/recipes-bsp/device-tree/files/system-user.dtsi. An example of the file is listed below with reserved memory for DMAs ( LINK ). Reserved memory is useful for manually controlling the DMAs inside the PL. In case the memory is not reserved, then system may write to the location and not knowing,that there are some transfers running in the background. The DT overlay should be enabled in petalinux-config in order to make nodes such as &spi0 / &spi1 / &sdhci0 visible. A common error of compiling the devicetree is to address the common nodes inside the /{ }; section, but they need to be modified outside the scope such as shown below:

/include/ "system-conf.dtsi"
/ {

  // Reserve 512MB for DMAs in Memory range 32GB + 1.5GB -> 32GB + 2GB.
  // This is the DDR_HIGH Address range in Zynq U+. See Address Maps TRM.
  reserved-memory {
    #address-cells = <2>;
    #size-cells = <2>;
    ranges;

    reserved:buffer@0{
      compatible = "shared-dma-pool";
      no-map;
      reg = <0x08 0x60000000 0x0 0x20000000>    
    };
  };

  reserved-driver@0 {
    compatible = "xlnx,reserved-memory";
    memory-region = <&reserved>;
  };
};

// Make Modifications to other nodes
&sdhci0 {
  status = "okay";
};

Once the linux distribution is up and running, In order to have a set of scripts, that are executed during system startup,browse to /etc/init.d and customize scripts already launched after startup. In order to create a custom initialization script (Such that network mount, package update, interface configuration and so on …) create an .sh file and place it in /etc/rcS.d/S99_MYSCRIPT.sh. By default, all initialization scripts (Starting with “S” prefix) are executed from this directory alphabetically. That is why additional prefix such as 99 is required and or at least recommended. 

Final Notes on Petalinx:

The Petalinux is a great tool for building a bootable Linux image in a relatively simple way. Despite this, one cannot expect to be successful during first compilation and boot. From my own experience, there will very likely be difficulties of different kinds, starting with compilation problems, dependencies, package compatibilities and OS support for Petalinux. Problems with device tree files and kernel drives are quite common I would say. What is also embarrassing is that petalinux needs plenty of resources. I do recommend to dedicate at least of 6GB of RAM for the virtual machine and use 256GB virtual hard drive due to the fact, that each petalinux project needs plenty of space on the hard drive. I have personally seen project sizes of up to 60GB, though the required size is usually based on the components selected for the Linux environment. Plenty of .bsp files comes with http server, python, GUI and so on. These components then “virtually eat the hard drive”. That is why I suggest not to use the BSP files,but rather start from scratch with your own design. A base project with drivers and common utilities should not exceed the size of approx 15GB. By the way Baobab is a great tool for disk usage analysis. In the end, I can say that  petalinux is a great tool for starters, but for advanced users, I would recommend to create, build, configure and compile most of the sources by hand and downloading only the necessary Xilinx source files from the repositories mentioned. 

I would also recommend to keep your directory structure well organized!

Take a look at the available boards from varius vendors: