After creating a base hardware design in Vivado 2023.2 for my Arty Z7 development board, I also wanted to build an embedded Linux image to run on it. This is what AMD's Yocto-based PetaLinux toolset is for. So in this project tutorial, I'll be walking through how to build that Linux image in PetaLinux 2023.2 for my Arty Z7.
For new users to PetaLinux it's worth noting a couple of things:
1 - The same version of Vivado must be used to create the hardware design (XSA file) as the version of PetaLinux being using to build the Linux image. So I'm using PetaLinux 2023.2 and the hardware design I created was exported from Vivado 2023.2
2 - Unless the PetaLinux project is specifically configured to run a build offline, a network connection is required on the host PC when building the PetaLinux project. This tutorial is for the standard build that requires a network connection for a build.
Also, see my previous tutorial for installation instructions of PetaLinux 2023.2 itself on a Ubuntu-based host PC.
Create PetaLinux ProjectOpen a new terminal window, source the PetaLinux tools to the environment, and create a new PetaLinux project.
The petalinux-create
command requires three main options when creating a new project: the type
flag to specify that a project is being created, the template
flag specifies the target processor in the hardware design which in the case of the Arty Z7 is the Zynq, and the name
flag which specifies the PetaLinux project name (which is the name of the top level directory of the project).
The petalinux-create
command creates the project within the directory where the command is issued, so be sure to change directories into the desired location beforehand.
~$ source /tools/Xilinx/PetaLinux/2023.2/settings.sh
~$ cd ./<desired prj dir>
~$ $ petalinux-create --type project --template zynq --name <desired prj name>
To keep things organized, I like to create the PetaLinux project in the top level directory of the Vivado project that I created the hardware design in:
~$ source /tools/Xilinx/PetaLinux/2023.2/settings.sh
~$ cd ./artyz7_prj0/
~/artyz7_prj0$ petalinux-create --type project --template zynq --name linux_workspace
Import Hardware XSA FileAfter the project is created, changed directories into the new project and import the hardware XSA file exported from Vivado to configure the Linux image for the given hardware (ie - boot from an SD card vs QSPI, with UART interface to use, etc.).
~$ cd ./<petalinux prj dir>/
~$ petalinux-config --get-hw-description ./<location of XSA file>
When providing the location of the XSA file, only specify the directory where it is located. Since my PetaLinux project is in the top level directory of the Vivado project where I exported the XSA to, I just specified the directory one level above the PetaLinux project.
~/artyz7_prj0$ cd ./linux_workspace/
~/artyz7_prj0/linux_workspace$ petalinux-config --get-hw-description ../
Configure Linux for Hardware OptionsOnce PetaLinux successfully reads in the the XSA file, it will automatically launch the hardware configuration ASCII GUI. Hardware options such as which UART interface, Ethernet controller, etc. are automatically detected based on how the Zynq Processing System IP is configured in the block design of the Vivado project (located un Subsystem AUTO Hardware Settings).
By default, PetaLinux configures the image to boot using initial RAM disk (initrd). I personally prefer to use a EXT4 filesystem type located on an SD card. So under Image Packaging Configuration > Root filesystem type, I changed it from INITRD to EXT4 (SD/eMMC/SATA/USB).
TFTP boot is also enabled by default, which I don't plan to use for this image so I also disabled that. Then when exiting the configuration GUI, if any changes are made a prompt will appear asking to save/apply the changes.
Configure the Linux OSThe default configuration of a PetaLinux project usually allows for the the FPGA board to boot at least. To configure the Linux image to add kernel drivers, libraries in the root filesystem, option in the secondary Linux boot loader (u-boot). This is where the petalinux-config
command with -c
flag (component) comes in.
The petalinux-config
command with no options passed will reopen the hardware configuration GUI, but using the component flag with specified Linux OS component to configure will open the configuration GUI for that component.
~$ petalinux-config -c <Linux OS component to configure>
So to configure the u-boot, kernel, or root filesystem, the commands would be:
~$ petalinux-config -c u-boot
~$ petalinux-config -c kernel
~$ petalinux-config -c rootfs
For this basic image I didn't add anything, but I probably will come back later to add things as needed.
Build PetaLinux ProjectOnce all of the setting are configured as needed, build the project with the petalinux-build
command:
~$ petalinux-build
The first build or a clean build of a project will take the longest depending on how many root filesystem libraries and/or kernel drivers have been enabled. Which is part of the reason I like doing an initial build before adding any additional libraries/kernels.
~/artyz7_prj0/linux_workspace$ petalinux-build
This is the first 2023.2 PetaLinux project that I have built and I got a warning message that I hadn't seen before, but it didn't appear to affect anything so I think it's safe to ignore for now.
The petalinux-package command has a handy option for building a wic image that can be flashed onto an SD card using a program like balenaEtcher.
Use the --wic
flag with --bootfiles
flag to specify which files go in the boot partition of the SD card, and the --rootfs-file
flag to specify which root filesystem packaged file to extract on the root filesystem partition of the SD card. The boot binary (boot.bin) has to be generated separately first since what gets packaged into it varies per design depending on how PetaLinux was configured to launch Linux on the target. For the Arty Z7 in this instance, the Zynq FSBL, FPGA bitstream, and secondary boot loader (u-boot) are all that goes into the boot binary:
~$ petalinux-package --boot --fsbl ./images/linux/zynq_fsbl.elf --fpga ./images/linux/system.bit --u-boot
~$ petalinux-package --wic --bootfiles "BOOT.BIN image.ub system.dtb boot.scr" --rootfs-file ./images/linux/rootfs.tar.gz
Typically, all that is needed for the boot partition is the boot binary (BOOT.BIN), kernel image (image.ub), device tree blob (system.dtb), and boot script (boot.scr). The packaged root filesystem to use is rootfs.tar.gz. These files are located in the./images/linux directory of the PetaLinux project which appears after a successful build.
~/artyz7_prj0/linux_workspace$ petalinux-package --boot --fsbl ./images/linux/zynq_fsbl.elf --fpga ./images/linux/system.bit --u-boot
~/artyz7_prj0/linux_workspace$ petalinux-package --wic --bootfiles "BOOT.BIN image.ub system.dtb boot.scr" --rootfs-file ./images/linux/rootfs.tar.gz
Flash SD CardOnce the wic image has been successfully generated, use an application such as balenaEtcher to flash an SD card.
Through trial and error, I've found that it's best to use class 10 SD cards from SanDisk. The required size depends on the libraries and drivers added, as well as the space needed by the applications running on the Linux image. However I've found that 8GB and 16GB SD cards are sufficient for the majority of my uses.
Boot Arty Z7Install the SD card in the slot on the bottom of the Arty board, and change jumper JP4 to SD to tell the Zynq to boot from the SD card:
If powering via the USB JTAG (PROG UART) connector, set JP5 to USB. If powering with the wall wart via the barrel jack, set JP5 to REG. Since I'm not doing anything super resource intensive in this design, I'm just powering the Arty board over the USB JTAG port. But keep in mind that this may not provide enough power for all designs.
Connect USB cable to PROG UART connector, which will also power on the Arty board to begin the Linux boot sequence.
Connect to the UART serial terminal of the Arty using an application such as Putty or TeraTerm. When the login prompt shows up, log in with the username petalinux and change the user password when prompted.
In my base hardware design for the Arty Z7 that I created in Vivado, I connected all of the GPIO peripherals on the board to their own AXI GPIO IPs. This ultimately translates to each AXI GPIO having its own node in the Linux device tree and each showing up as a separate device in the Linux user space.
Use the following commands to verify that the AXI GPIO IP blocks from the hardware design added to control the various peripherals on the Arty board show up in the Linux environment properly:
~$ ls /dev/gpio*
~$ ls /sys/bus/gpio/devices
Checking that each shows up in the /dev
directory verfies that GPIO block shows up as a device in the Linux userspace. Then verifying that each shows up in the /sys/bus/gpio/devices
directory verifies that they are properly bound to the GPIO Sysfs driver to control them.
Read the details here for how to drive the GPIO from the Linux userspace.
ShutdownNow that the Linux image has been validated on the Arty board, the final note to mention is how to properly shut down the Linux OS. If power is just removed from the Arty board before a clean shutdown as been performed of Linux, then there is the chance that the image on the SD card will become corrupt.
To safely shutdown the Linux OS use the following command:
~$ sudo shutdown -h now
Wait until you see the text reboot: System halted
before removing power from the Arty board.
Comments
Please log in or sign up to comment.