In my last project post, I covered the foundation of creating a fixed platform hardware design for the Zynq-7000 SoC FPGA in Vivado 2024.1, and how the next steps after exporting the XSA file was to decide the type of software to run on the ARM-core of the Zynq FPGA to determine the workflow in Vitis and PetaLinux.
Quick side note, the versions of Vivado, Vitis, and PetaLinux all have to match each other within the workflow of a given design. Meaning that a hardware design created in Vivado 2024.1 can only be exported to use in Vitis 2024.1 and PetaLinux 2024.1.
In this write-up I will go over the general workflow of creating either a standalone (no operating system/no-OS) or Linux-based application to run on the ARM-core of the Zynq-7000 SoC using the Vitis Unified IDE for a fixed platform design (assuming you already have the sysroot generated from PetaLinux for a Linux-based application - explained in later sections). I am using am Ubuntu 22.04 host PC, but the entirely of this project is no different if using a Windows host PC.
The only difference between a Windows development host and a Linux development host for the AMD FPGA tools is with PetaLinux (which is required to create the sysroot for a Linux-based application to run on the Zynq, thus why I'm mentioning it here). PetaLinux can only be installed/ran on a Linux development host. So Windows users would need some sort of virtual machine or emulation option like WSL, although it's worth noting that AMD only provides official support for native Linux installs on host develpment systems.
From personal experience, I highly recommend using a Linux host PC if PetaLinux is needed for your workflow (Linux is better than Windows anyways haha).
Create Vitis WorkspaceFirst, something that can throw a new-to-Vitis user off, is that there is no explicit option to create a new workspace (aka project) in the Vitis Unified IDE. The action of opening a workspace in an empty directory is how a "new" workspace is created.
A Vitis workspace can be created in any desired directory, personally I like to create a folder titled "vitis_workspace" in the top level directory of the corresponding Vivado project that the hardware design XSA file was exported from.
This way I don't have to try to remember which Vivado project created the hardware design the application is based on, because other than user naming conventions there is no way to keep track of what Vivado project an XSA
The Vitis Unified IDE can either be launched directly from Vivado (select Tools > Launch Vitis IDE) or from the command line by sourcing the tools to the environment then launching it.
Here are the Linux-based commands to launch Vitis from the command line:
~$ source /<path to Xilinx install>/Vitis/2024.1/settings.sh
~$ vitis
Once the Vitis IDE has opened, select Open Workspace from the left-hand navigation pane and point to the desired empty directory you want to be your workspace for the project.
With a workspace now opened, the options in the left-hand navigation pane will change to give you the option to create the various components required to develop a software application to run on the Zynq-7000.
If creating a Linux-based application to run on the Zynq-7000, Vitis requires a sysroot of the Linux image that will be running on the Zynq in order to be able to cross-compile the application on your host PC.
As I mentioned previously, this requires PetaLinux which can only be used on a Linux host. However it is possible to move an extracted sysroot to a Windows machine.
The following steps are just for creating a sysroot for a given PetaLinux project, as the full detail for building the PetaLinux project itself would make this post too long (see the corresponding PetaLinux project tutorial write-up here).
First, to build the SDK for the sysroot, use the petalinux-build
command with the --sdk
flag:
~$ petalinux-build --sdk
Then
extract the sysroot into the desired directory for use:
~$ ./sdk.sh -dir <path to install dir>
The sysroots
directory that is created at this point is what can be copied over to Windows.
Again for organization purposes, I like to extract the sysroot in-situ in the PetaLinux output directory (<PetaLinux project directory>/images/linux
). The 2024.1 version automatically creates a subdirectory titled ir
that it places the extracted sysroot in.
~/<path to petalinux project>/images/linux$ ./sdk.sh -dir ./
In a Vitis workspace, there are two main types of components created: platform components and application components. Application components contain the source code for the application itself, and platform components that take the hardware definition XSA file and extract it into the board support package (BSP).
Since the BSP needs to exist first for the application source code to be built on, a platform component needs to be created first.
Select Create Platform Component from the left-hand navigation pane and give it the desired name.
On the next page, point to the XSA file exported from Vivado. Since this is a fixed platform design there is no need for hardware emulation and the XSA option for it can be left blank, same for the advanced options.
Once the XSA has been specified, the target ARM-core of the Zynq chip for the software to run on and the target operating system.
The Zynq-7000 has two Arm® Cortex®-A9 processing cores to select from, and the target OS can be standalone/no-OS (meaning C code is running directly on the core with no operating system), Linux, or RTOS.
Side note: The combination of target processor and target OS creates a "domain" in the platform component, and platforms can have multiple domains. So while I created the standalone/no-OS domain first here, a second Linux domain can be created later (shown in later steps).
The final page of the creation wizard shows a summary of the selections, and the Back button can be used to step back to make any modifications before clicking Finish to generate the platform in the workspace.
Once the platform component has been generated, if the target OS is standalone, go ahead and run a build to verify there are no errors. Click Build in the Flow window in the lower section on the left-hand navigation pane.
If the target OS is Linux, there is some configuration required before running a build.
Configure Linux Domain in Platform ComponentUnder the hood, Vitis is cross-compiling the Linux application software being developed to run on the ARM-core of the Zynq-7000, so it needs access to the necessary components of the target Linux operating system.
Quick note: I had created the standalone domain first, so that is the only reason it is seen in the screenshots here. If you have only created a Linux domain then don't worry about the standalone domain not appearing the same as in my screenshots.
Open the vitis-comp.json file under the Settings directory of the platform component.
Select the Linux domain created when the platform component was created (and Linux was selected as the target OS) or when the new Linux application was created and it created the new Linux domain in the platform if it wasn't already present.
This is where the components of the target Linux OS that will be running on the Zynq are specified so Vitis is able to cross compile the application software.
This also includes mimicking the boot and root filesystem directories that would be on the target FPGA's SD card or eMMC.
Since the rest of the target Linux OS components are in the corresponding PetaLinux project's output directory (<PetaLinux project directory>/images/linux
), and I have already extracted the sysroot there, I like to create another directory in the top level of the extracted sysroot titled sd_card
. Then within sd_card
, two folders for the boot and root filesystem directories titled boot
and sd_dir
.
After creating the folders to mimic the boot and root filesystem directories, return to the Linux domain in Vitis.
Use the door/arrow icon next to Browse for the Bif File to generate it. Then set the Pre-Built Image Directory and Qemu Data paths to the mimic boot
directory, set the FAT32 Partition Directory to the mimic sd_dir
directory, and point to the output device tree blob from the PetaLinux project for the DTB File.
Also copy boot script (boot.scr), Linux kernel (image.ub), device tree blob (system.dtb), Linux secondary bootloader (uboot.elf), and the Zynq's first-stage bootloader (zynq_fsbl.elf) from the PetaLinux project output directory to the mimic boot
directory:
Once the Linux domain has been configured in the platform, run a build to verify there are no errors.
Once a platform component has been created and built, an application component can be created to run on it.
There are two ways to create an application component. Under the File menu, there is the option Create New Component > Application Component. However, this option only allows for a blank application component to be created. The application template option has been moved in the Vitis Unified IDE.
I personally always like to use the application templates because it cuts out some configuration I would otherwise have to do with a blank application.
To find the application templates to create an application component from, switch to the Welcome tab.
Then select Examples under Get Started to open the repository of application templates in the left-hand navigation pane:
Select the desired standalone application template to use, in this case I'm using the Hello World application template (which is what I use most of the time). Then click Create Application Component from Template:
Even though the Hello World template is being used, the application component can be renamed to whatever is desired:
Select the platform component created in the previous steps to build the application component on.
Then select the corresponding domain for standalone on the ARM-core of the Zynq (it will be the only option if other domains have not been created yet):
Finally, review the selections of the configuration of the application before clicking Finish to create it.
After generating the new application component, Vitis will automatically open the configuration vitis-comp.json file for it:
The source code files for the application live under Sources > src:
The code in helloworld.c can modified directly or a new main file can be imported (along with other sources files) by right-clicking on the src directory and selecting Import > Files...
The Vitis Unified IDE gets bonus points because the Folders... option lets you select a folder to import with all files that are within it. This was a pain in previous versions of Vitis Classic and XSDK because you would have to manually create the subdirectories within src then import the files into them.
Create Application Component (Linux OS)To create a Linux application component from a template, return to the examples repository and select one that supports the Linux domain. In this case, I'm using the Linux Hello World template:
Again, it can be renamed to whatever is desired:
And select the platform component created in previous steps.
At this point, when selecting the domain for Linux, if the domain has already been created because it was the target OS selected when the platform component was created, then it will automatically be filled in here.
In my case, I created the standalone domain first (ie - selected standalone as the target OS when I initially created the platform component), so no Linux domain existed when I created the Linux application component.
Because no Linux domain exists, the creation wizard of the Linux application component will prompt you to create it here.
Select Linux as the target operation system for the domain and the target ARM processing core.
After selecting/creating the Linux domain in the platform component, point the application component to the extracted sysroot done in previous steps:
Finally, review the selections before clicking Finish to generate the Linux application component.
Again, once Vitis generates the application component, it will automatically open the vitis-comp.json configuration file from the Settings folder. The source code is stored under Sources > src, and custom source files can be imported the same as with the standalone application by right-clicking on the src directory Import > Files... or Folders...
Once the application component has been generated, I like to run a quick build before modifying anything just to make sure there are no foundation configuration errors.
As a quick note for Vitis 2024.1 on Ubuntu 22.04 (although I've seen others report this issue on Windows 11 as well), despite uninstalling/reinstalling the required versions of clang and llvm, I get these phantom errors reporting there is an issue with clang so certain header source files can't be found or certain relative functions can't be called. Despite these errors, the application still builds successfully and I haven't found any actual impact on the workflow or functionality of the application so far. I'm still working to find a solution for this, which I will update my 2024.1 installation tutorial with.
Run Debugger (Standalone/no-OS)To debug a standalone application on the target FPGA board, start by connecting the board to the host PC via its JTAG port (which can be via a USB port with FTDI chip or straight JTAG port) and configure it to boot from JTAG (usually done via a physical switch configuration).
In my case, I am using Digilent's Zybo FPGA development board, so the JTAG is routed to a USB port via an FTDI chip and a header with jumper sets the boot mode:
Once the board is connected to the host PC, power it on and open the Debug configuration window by selecting the standalone application from the dropdown in the Flow window, hover over the word Debug and click the gear icon that appears next to the word Debug.
Validate that Board Initialization is set to FSBL (which is the Zynq first-stage bootloader), and the rest of the settings should fill automatically if the component was created properly.
Once the debug run settings have been validated, click on the word Debug in the Flow window for the standalone application component to launch the debug run.
The Vitis Unified IDE will automatically switch to the debugger view and stop at an auto-set breakpoint at the entrance of the main function. The tools for stepping through the code, showing the call stack, viewing memory locations, etc. all become available once the application is successfully running (ie - when it hits that auto-set breakpoint at the entrance of the main function):
Before stepping through the function, there is the opportunity to open a Putty terminal to connect to the FPGA's serial output, where the print statements can then be monitored in real time as the application code is stepped through.
To terminate the debug session and disconnect, click the red square icon. Once terminated, click the home icon in the upper left-hand corner to return to the regular development view.
Run Debugger (Linux OS)Launching a debug run for a Linux application is very similar expect instead of booting the target FPGA in JTAG mode, it needs to be booted normally into the Linux OS built for it and the sysroot came from that the application component was compiled with.
Once the target FPGA board has been booting up running its Linux OS, connect it to the same local area network as the host PC Vitis is running on via the board's Ethernet connector. This is so Vitis can connect to it with the Linux TCF Agent.
Before launching the debug run, the TCF Agent connection in Vitis needs to be established/verified. Select the Vitis menu tab then Target Connections...
Double-click on Linux Agent under Linux TCF Agent:
The default local IP address that the Linux TCF Agent uses is 192.168.0.1
Switching over to the serial terminal in Putty that's connected to my Zybo running its Linux OS, I used the ifconfig
command to double-check its local IP address (which is turned out to be 192.168.1.147):
Since my target FPGA board's (the Zybo's) IP address is different, I updated the Host IP address of the Linux TCF Agent in Vitis to match it:
Then use the Test Connection button to establish/validate the connection:
Once the Linux TCF Agent is connected to the target FPGA board, open the Debug configuration window by selecting the Linux application from the dropdown in the Flow window, hover over the word Debug and click the gear icon that appears next to the word Debug.
Update the Work Directory to /home/petalinux. This is to match the directory structure of the Linux image running on the target FPGA board.
Open the source code and set the desired breakpoint, which in my case is the print statement in the main function of helloworld.c:
Then click the word Debug in the Flow window for the Linux application component to launch the debug run:
Uploading the Linux application is covered in the corresponding PetaLinux tutorial for this series of fixed designs on Zynq-7000 in the 2024.1 version of the AMD FPGA tools.
For standalone applications, to upload the application hardware "permanently" means that the.elf file for the application is packaged into an.mcs file which is then programmed onto the target FPGA board's flash memory which is non-volatile.
To create the.mcs file select the standalone application from the dropdown in the Flow window, and click Create Boot Image.
Change the Output format from BIN to MCS:
Click Browse next to Output BIF File Path to generate the.bif file with the desired name:
When the.bif file is generated, it will automatically create the.mcs file title BOOT.mcs:
Which can be found in the application component directory in the Vitis workspace:
Then to program the.mcs onto the target FPGA board's flash, select Vitis > Program Flash:
Vitis will autofill most of the settings on its own, the specific.mcs file to flash just needs to be specified. Select Browse next to Image File:
And select the BOOT.mcs generated in the previous steps:
I recommend enabling the Verifiy after flash option, then click Program to program the BOOT.mcs onto the target FPGA board's flash memory.
And that's my overview of the 2024.1 Vitis Unified IDE for fixed platform designs on Zynq-7000 based FPGA boards. See the corresponding Vivado and PetaLinux posts to complete the overall workflow for fixed platform designs on Zynq-7000 based FPGA boards and let me know if I missed anything!
Comments
Please log in or sign up to comment.