Xilinx Software Command Line Tool (XSCT)
- Introduction
- Environment and Workspace for XSCT
- Platform Projects in XSCT
- Application Projects in XSCT
- Using scripts with XSCT
- Creating and Testing a Boot Image
Introduction
The Xilinx Software Command-line Tool (XSCT) is an interactive and scriptable command-line interface to Xilinx software development tools. Basically, it allows to perform all of the operations that the Eclipse based interface of Vitis supports but from a shell environment, including:
- Creating and managing projects:
- Platform Projects
- Application Projects
- System Projects
- Accessing the JTAG to:
- Debug applications
- Program the FPGA
In order to illustrate how useful the XSCT workflow may be, we will use it to generate the first hardware-dependent software components we need to create a Linux runtime into the Ultra96-V2 board, i.e.:
- The First Stage Boot Loader.
- The Platform Management Unit Firmware.
NOTE: Of course, both the First Stage Boot Loader and the PMU Firmware can be generated by using the Eclipse based Vitis graphical interface too.
Environment and Workspace for XSCT
Before starting to work, we create a folder for the components of the Linux runtime we plan to build.
mkdir -p ~/soc-course/linux
Then, we need to get the exported Xilinx Shell Archive (XSA) from the Vivado project we want to support in our Linux runtime. As a complete example, we will use the ultra96v2_custom.xsa design with custom peripherals in the programmable logic. For an easier path management, we will copy the file into a new hardware directory inside the Linux related one:
mkdir -p ~/soc-course/linux/hardware
cp ~/soc-course/vivado/ultra96v2_custom/ultra96v2_custom.xsa ~/soc-course/linux/hardware/
Finally, as XSCT is basically a command line interface for Vitis, we need to create a directory that will act as the workspace for the platform, application and system projects we plan to create:
mkdir -p ~/soc-course/linux/xsct_ws
For easier path handling, we move into the linux directory:
cd ~/soc-course/linux/
Now, we need to load the Xilinx Vitis environment script and open the Xilinx Software Command-line Tool (XSCT):
source /tools/Xilinx/Vitis/2019.2/settings64.sh
export LC_ALL="C"
xsct
NOTE: From now onward, unless otherwise is specified, all of the commands will be executed from the xsct shell, not the Linux one:
Once we are inside the XSCT shell, before starting to work, we need to set the workspace for our projects, just as we did with the Eclipse based Vitis environment:
setws ~/soc-course/linux/xsct_ws
Platform Projects in XSCT
Our first task is creating a new platform project, an we can get help on creating platforms with:
platform create -help
We create an empty platform associated to our hardware, with no default domain nor boot elements:
platform create -name ultra96v2_custom_platform -hw hardware/ultra96v2_custom.xsa -no-boot-bsp
Now, we can check this is the active platform with:
platform active
If we have several platforms in the workspace, we can use this very same command to set the active platform:
platform active ultra96v2_custom_platform
Creating a Domain for FSBL
We can get the help on creating new domains in the active platform:
domain create -help
So, we will start with creating a domain named fsbl_domain for the FSBL in the psu_cortexa53_0 processor:
domain create -name "fsbl_domain" -os standalone -proc psu_cortexa53_0
We can check the active domain with:
domain active
And the complete list of domains in the active platform with (an asterisk marks the active one):
domain list
We can operate in the Board Support Package of the active domain by using the bsp command:
bsp -help
In order to print the information about the Operating System in the domain, we use:
bsp getos
In the same way, the available peripherals and associated drivers in the BSP are listed with:
bsp getdrivers
Regarding libraries, we can get the available ones with, and we will check that this list is empty:
bsp getlibs
Because we are building a domain for a FSBL, we must add the required libraries for this kind of application, i.e.:
- xilffs
- xilsecure
- xilpm
We can do this with the following command:
bsp setlib xilffs
bsp setlib xilsecure
bsp setlib xilpm
After doing this, we can check that these have been successfully added to the BSP with:
bsp getlibs
Before moving forward, we can check the parameters for our Operating System in the BSP with:
bsp listparams -os
Now, remember that the Ultra96-V2 is using the UART 1, so we need to change stdin and stdout configuration in the BSP:
bsp config stdin psu_uart_1
bsp config stdout psu_uart_1
In addition, we need can optionally enable the zynq_fsbl_bsp optimizations with:
bsp config zynqmp_fsbl_bsp true
After doing this, we can review that the changes have been actually applied:
bsp listparams -os
Creating a Domain for PMU Firmware
Once the fsbl domain is configured, we can create a domain named pmufw_domain for the PMU Firmware in the psu_pmu_0 processor:
domain create -name "pmufw_domain" -os standalone -proc psu_pmu_0
After doing this, our first domain will be automatically build before activating the new domain for the PMU Firmaware. We can check that we have two domains now in the active platform and that pmufw_domain is the active one with:
domain list
As we did before, we can review the available peripherals and drivers with:
bsp getdrivers
Regarding libraries, we can get the available ones in the BSP with the following command:
bsp getlibs
Now we will check that this list is actually populated with the required ones for a PMU Firmware BSP (note that there is no other kind of application but the PMU Firmware for the Platform Management Unit), i.e.:
- xilfpga
- xilsecure
- xilskey
If this is not the case or any of them is missing, we could add the the required libraries with these commands:
bsp setlib xilfpga
bsp setlib xilsecure
bsp setlib xilskey
Before moving forward, we can check the parameters for our Operating System in the BSP with:
bsp listparams -os
Once again, as the Ultra96-V2 is using the UART 1, we need to change stdin and stdout configuration in the BSP:
bsp config stdin psu_uart_1
bsp config stdout psu_uart_1
After doing this, we can review that the changes have been actually applied:
bsp listparams -os
Building the Platform
Once we have finished creating the domains and configuring the associated BSPs, we can build the platform with the following command:
platform generate
Application Projects in XSCT
As a final step, we need to create the applications for both the FSBL and the PMU Firmware.
Creating the FSBL and PMU Firmware applications
First, you can retrieve the complete list of available templates with:
repo -apps
We can get help on creating applications with:
app create -help
First, we create the application for the FSBL targeting the already existing platform and the specific domain and specifying the template Zynq MP FSBL. In addition, we will select the ultra96v2_custom_system as the name of the system that will be created to host the application:
app create -name zynqmp_fsbl -template {Zynq MP FSBL} -platform ultra96v2_custom_platform -domain fsbl_domain -sysproj ultra96v2_custom_system
Then, we create the application for the PMU Firmware by targeting the already existing platform and the specific domain and specifying the template ZynqMP PMU Firmware. We will select the ultra96v2_custom_system system project that was created previously to host both of the applications in the same one:
app create -name zynqmp_pmufw -template {ZynqMP PMU Firmware} -platform ultra96v2_custom_platform -domain pmufw_domain -sysproj ultra96v2_custom_system
Configuring the FSBL and PMU Firmware applications
Once the applications are created, we can get help on how to configure them with:
app config -help
If we want to know the available configuration settings for the zynqmp_fsbl and zynqmp_pmufw apps, we use:
app config -name zynqmp_fsbl
app config -name zynqmp_pmufw
As an example, we can check the build configuration for zynqmp_fsbl and zynqmp_pmufw with:
app config -name zynqmp_fsbl build-config
app config -name zynqmp_pmufw build-config
We can see that both of them are in debug mode, so we can just change them to release as we do not plan to debug them:
app config -name zynqmp_fsbl build-config release
app config -name zynqmp_pmufw build-config release
Now, we can check that the changes have been successfully applied with:
app config -name zynqmp_fsbl build-config
app config -name zynqmp_pmufw build-config
Building the FSBL and PMU Firmware applications
Once the applications have been successfully configured, we can proceed with building them:
app build -name zynqmp_fsbl
app build -name zynqmp_pmufw
In we need to clean the applications after they have been built, we would use:
app clean -name zynqmp_fsbl
app clean -name zynqmp_pmufw
Once we have finished, we can just close the XSCT with the following command and go back to the Linux terminal:
exit
Using scripts with XSCT
The main advantage of using XSCT over using the Vitis graphical interface is that you can include the previous commands into TCL scripts so that the procedure can be easily replicated.
As an example, we can go to the folder we created to contain our Linux components and create inside a script named xsct_script.tcl by using your preferred text editor:
cd ~/soc-course/linux
vi xsct_script.tcl
Now, we can copy the following content to reproduce the steps performed in the previous section or simply download the xsct_script.tcl file:
# Set the Workspace
setws ~/soc-course/linux/xsct_ws
# Create the platform
platform create -name ultra96v2_custom_platform \
-hw hardware/ultra96v2_custom.xsa -no-boot-bsp
platform active ultra96v2_custom_platform
# Create the FSBL Domain
domain create -name "fsbl_domain" \
-os standalone -proc psu_cortexa53_0
bsp setlib xilffs
bsp setlib xilsecure
bsp setlib xilpm
bsp config stdin psu_uart_1
bsp config stdout psu_uart_1
bsp config zynqmp_fsbl_bsp true
# Create the PMU FW Domain
domain create -name "pmufw_domain" \
-os standalone -proc psu_pmu_0
bsp setlib xilfpga
bsp setlib xilsecure
bsp setlib xilskey
bsp config stdin psu_uart_1
bsp config stdout psu_uart_1
# Generate the platform
platform generate
# Create the applications
app create -name zynqmp_fsbl -template {Zynq MP FSBL} \
-platform ultra96v2_custom_platform \
-domain fsbl_domain -sysproj ultra96v2_custom_system
app create -name zynqmp_pmufw -template {ZynqMP PMU Firmware} \
-platform ultra96v2_custom_platform \
-domain pmufw_domain -sysproj ultra96v2_custom_system
# Configure the applications
app config -name zynqmp_fsbl build-config release
app config -name zynqmp_pmufw build-config release
# Build the applications
app build -name zynqmp_fsbl
app build -name zynqmp_pmufw
Once done, if we want to try the script, we must remove and re-create the workspace directory:
rm -r ~/soc-course/linux/xsct_ws
mkdir ~/soc-course/linux/xsct_ws
Finally, in order to launch it, we can just call the XSCT program from the Linux shell and provide the path to the script as an argument, i.e.:
xsct ./xsct_script.tcl
Creating and Testing a Boot Image
Now that we have build the first of the components we need for booting a Linux runtime, we can create a boot image containing the following partitions:
- First Stage Boot Loader for Cortex-A53 0
- PMU Firmware for Platform Management Unit
- Bitstream for Programmable Logic
This can be done by creating a xsct_flow.bif file inside the linux folder (this is just for relative path convenience, modify as per your setup):
cd ~/soc-course/linux
vi xsct_flow.bif
And copy this content (note that we are using FSBL to load the PMU Firmware in order to see its messages in stdout):
/* Linux */
the_ROM_image:
{
[bootloader, destination_cpu = a53-0] xsct_ws/zynqmp_fsbl/Release/zynqmp_fsbl.elf
[destination_cpu = pmu] xsct_ws/zynqmp_pmufw/Release/zynqmp_pmufw.elf
[destination_device = pl] xsct_ws/ultra96v2_custom_platform/hw/ultra96v2_custom.bit
}
Now, we can generate the Boot Image with the bootgen command line tool:
bootgen -image xsct_flow.bif -arch zynqmp -w -o BOOT.bin
Then, we can copy the BOOT.bin image to the FAT partition of the microSD and configure the Ultra96-V2 Boot Mode to SD:
- Switch 1: OFF
- Switch 2: ON
Now, we need to open a serial terminal in /dev/ttyUSB1 and then we power-up the board.
If everything goes well, we should see:
- In the Ultra96-V2 board, the blue LED named DONE (close to the microSD) is ON, indicating that the bitstream has been successfully programmed.
- In the serial terminal, we will get the messages coming from the First Stage Boot Loader and the PMU Firmware, e.g.:
Xilinx Zynq MP First Stage Boot Loader
Release 2019.2 Jun 15 2020 - 15:27:58
PMU Firmware 2019.2 Jun 15 2020 15:23:57
PMU_ROM Version: xpbr-v8.1.0-0