cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Creating a Linux user application in Vitis on a Zynq UltraScale Device

stephenm
Moderator
Moderator
13 20 5,185

One of the most fundamental tasks in Linux embedded design is creating a user application.

In this blog, I will showcase a simple LED toggling application run on a Linux kernel on a Zynq® UltraScale™ device. 

Hardware Design:

I am using a Zynq UltraScale+ MPSoC ZCU104 Evaluation board. However, the steps here should be agnostic to the device you are using. 

I have used Vivado® to create my block design. I have a Zynq UltraScale PS, and an AXI GPIO connected to the 4 LEDs on my ZCU104 board.

stephenm_0-1597946684737.png

The address map is shown below:

stephenm_1-1597946813753.png

I used the options below when creating the XSA:

stephenm_0-1597947832831.png

stephenm_1-1597947848694.png

Linux Image:

If you have a development board, it is recommended to use the BSP (if it exists).

However, in this example I will create it from the template. I have added the UIO drivers and will use this for the AXI GPIO.

I have also created the sysroot as this is needed in Vitis for cross compilation.

 

 

 

petalinux-create -t project --template zynqMP -n zcu104_linux 
cd zcu104_linux 
petalinux-config --get-hw-description=<path to xsa>
   DTG Settings -> (zcu104-revc)MACHINE_NAME
petalinux-config -c kernel
   Select Device Drivers -> Userspace I/O drivers
      <*> Userspace I/O platform driver with generic IRQ handing
      <*> Userspace platform driver with generic irq and dynamic memory

 

 

 

Replace the system-user.dtsi with the following:

/include/ "system-conf.dtsi"
/ {
    chosen {
        bootargs = "earlycon clk_ignore_unused   uio_pdrv_genirq.of_id=generic-uio";
        stdout-path = "serial0:115200n8";
    };
};
  
&axi_gpio_0 {
    compatible = "generic-uio";
};

Then run the following commands:

 

 

 

petalinux-build
cd images/linux
petalinux-build --sdk
petalinux-package --sysroot

 

 

 

Creating the Platform:

This is not required as users only need the sysroot in Vitis.

However, for ease of use we can create a platform that we can use in Vitis to create our Linux application.

First, let's set up the platform files. 

I have organized the platform files into a folder structure. This is not needed, but users need to be aware of the file paths in the BIF.

The BIF is used in bootgen to create the bootable image. Here we are only using placeholder file names.

mkdir -p sw_comp/src/a53/xrt/image
mkdir sw_comp/src/boot
  • Copy the image.ub, boot.scr and rootfs.cpio.gz files from the PetaLinux image/linux folder to sw_comp/src/a53/xrt/image 
  • Copy the system.bit, bl31.elf, uboot.elf, zynqmp_fsbl (renamed fsbl.elf), and pmufw.elf files from the PetaLinux image/linux folder to sw_comp/src/boot

Create the BIF:

the_ROM_image:
{
  [fsbl_config] a53_x64
  [bootloader] <zcu104_base/boot/fsbl.elf>
  [pmufw_image] <zcu104_base/boot/pmufw.elf>
  [destination_device=pl] <system.bit>
  [destination_cpu=a53-0, exception_level=el-3, trustzone] <zcu104_base/boot/bl31.elf>
  [destination_cpu=a53-0, exception_level=el-2] <zcu104_base/boot/u-boot.elf>
}

Copy linux.bif to sw_comp/src/boot.

Now create a new platform project in Vitis as follows:

stephenm_0-1598033024583.png

stephenm_1-1598033045155.png

stephenm_2-1598033065790.png

stephenm_4-1598033129956.png

stephenm_5-1598033225061.png

 

stephenm_6-1598033240458.png

This will create the platform in zcu104_base/export.

Creating the Linux Image in Vitis:

stephenm_0-1598033622500.png

Select a platform from the repository, click the + icon and browse to your platform.

stephenm_1-1598033643960.png

stephenm_2-1598033677727.png

Create a new application:

stephenm_3-1598033695425.png

Here, we can see that the Application settings are set by default using the settings in our platform.

stephenm_4-1598033708380.png

Select an Empty Application template, as we will be creating our own custom application.

stephenm_5-1598033733765.png

Right click on the src folder under the led_test app, and select New -> File

stephenm_6-1598033779305.png

Give this a file name (.c), and click Finish.

stephenm_7-1598033800378.png

You can now copy in the code below. This is a simple UIO example that will toggle the LEDs.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#define GPIO_MAP_SIZE           0x10000
#define GPIO_DATA               0x00
#define GPIO_TRI                0x04
#define LED_NUM             256

#define LED_DELAY             10000000


int main(int argc, char *argv[])
{
    int fd;
    char *uiod = "/dev/uio0";
    void *gpio_ptr;
    volatile int Delay;

    printf("AXI GPIO UIO test.\n");

    // open the UIO device file to allow access to the device in user space

    fd = open(uiod, O_RDWR);
    if (fd < 1) {
        printf("Invalid UIO device file:%s.\n", uiod);
        return -1;
    }

    // mmap the GPIO device into user space

    gpio_ptr = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    if (gpio_ptr == MAP_FAILED) {
        printf("Mmap call failure.\n");
        return -1;
    }

    // set bit0 on the GPIO to be output
    // see pg144 for ref

    *((volatile unsigned *)(gpio_ptr + GPIO_TRI)) = 0x0;


    // Toggle the LED
    while (1) {
        int i;
        unsigned char led_pin = 0x0;
        for (i = 0; i < LED_NUM; i++) {
            *((volatile unsigned *)(gpio_ptr + GPIO_DATA)) = led_pin;
            for (Delay = 0; Delay < LED_DELAY; Delay++);
            *((volatile unsigned *)(gpio_ptr + GPIO_DATA)) = 0x0;
            led_pin++;
        }
    }


    // unmap the GPIO device from user space

    munmap(gpio_ptr, 4096);
    return 0;
}

Select the system project, and click the hammer icon. This will build the executable and create the boot image.

stephenm_9-1598034884466.png

Testing on Hardware:

Copy all of the images from led_app_system\Debug\sd_card onto your SD card:

stephenm_10-1598035004971.png

Once booted, the SD card will be auto-mounted.

Change directory here, and execute the led_app.elf as shown below:

stephenm_12-1598035131067.png

You should also see the LEDs flashing on the board.

Use Ctrl + c to cancel.

Execute the Linux app Automatically:

The application above is run manually. However, users can create a recipe in Petalinux to load this into the rootfs, and run it.

To create the bootscript, users can use the command below:

  • petalinux-create --type apps --template install --name bootscript --enable

Then update the bootscript.bb file as shown below:

 

 

#
# This file is the bootscript recipe.
#

SUMMARY = "Simple bootscript application"
SECTION = "PETALINUX/apps"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"

SRC_URI = "file://hello_world.elf \
	   file://bootscript \
	"

S = "${WORKDIR}"

inherit update-rc.d
 
INITSCRIPT_NAME = "bootscript"
INITSCRIPT_PARAMS = "start 99 S ."

do_install() {
	     install -d ${D}/${bindir}
	     install -m 0755 ${S}/hello_world.elf ${D}/${bindir}
	     install -d ${D}${sysconfdir}/init.d
    	     install -m 0755 ${S}/bootscript ${D}${sysconfdir}/init.d/bootscript
}

FILES_${PN} += "${sysconfdir}/*"

 

 

Here I am loading the hello_world.elf created in Vitis into /usr/bin directory in the rootfs, and I am placing the bootscript in the init.d directory.

Note: Users can change the initlevel of the bootscript. For example:

 

INITSCRIPT_PARAMS = "start 99 5 . stop 20 0 1 6 ."

 

In this example, the script has a runlevel of 99, starts the script in initlevel  5, and stops the script in levels 0, 1 and 6. See here for more info

My bootscript looks like:

 

 

#!/bin/sh

echo "Executing User ELF"
./usr/bin/hello_world.elf

 

 

Then just build the petalinux image and boot. You should see your app running automatically:

app_boot.png

20 Comments
Christian_li
Newbie
Newbie

Could you tell more, how to create BIF (linux.bif) file?

stephenm
Moderator
Moderator

There is an example BIF that is provided here for reference. This is input into bootgen to create the boot image.

If you are using Petalinux, then the petalinux-package command can be used to create the boot image. This will create the BIF (in the build directory)

For more information on the BIF syntax, you can see the link below:

https://www.xilinx.com/html_docs/xilinx2020_1/vitis_doc/usingbootgenifs.html

joancab
Mentor
Mentor

Where it says:

Copy the image.ub, boot.scr and rootfs.cpio.gz files from the PetaLinux image/linux folder to sw_comp/src/a53/image 

It should read:

Copy the image.ub, boot.bin and rootfs.cpio.gz files from the PetaLinux image/linux folder to sw_comp/src/a53/xrt/image 

 

ok
Visitor
Visitor

Hi,

I did not understand , where you are running this below commands ..

petalinux-create -t project --template zynqMP -n zcu104_linux

 

Please help..me

Thanks
Ashok r

ok
Visitor
Visitor

Hi Stephen,

can you explain me how i can bypass the Linux Image part and use ZCu104 bsp instead.

my problem is i do not have Linux machine.

Thanks

Ashok r

maps-mpls
Mentor
Mentor

This blog is worth a lot, thank you!

stephenm
Moderator
Moderator

@ok if you want to use the bsp instead then use the instructions below:

petalinux-create -t project -s <path to bsp>

 

stephenm
Moderator
Moderator

@joancab cheers, this is is updated

doonny
Adventurer
Adventurer

@stephenmHi stephenm, great tutorial on this topic.

How can I integrate your design in the vitis application flow ?   I mean if I created an expandable project and export the vivado as a embedded platform, and use the platform to build an opencl application, will the UIO driver and your example code also work with the XRT runtime ?

stephenm
Moderator
Moderator

@doonny thanks for the feedback. The flow discussed above is how you would debug in the Vitis tool flow.

You just need to make sure that the UIO driver is enabled in your petalinux kernel settings (I think this is enabled by default)

There would be no issue using this with the XRT

alvin
Visitor
Visitor

Can you tell more details about bif file generating?

And you say petalinux-package can build it , but i could not found it , please help.

Or can you share the step by step of generate?

alvin
Visitor
Visitor

Hi @stephenm ,

 

I had executed "petalinux-package --sysroot" after "petalinux-build --sdk" succeed,

but it will print "unset LD_LIBARAY_PATH" message as below photo,

is it has any problems? please help,i am stocking right now.

圖片_2021-03-02_155913.png

stephenm
Moderator
Moderator

Was the sysroots created successfully? 

alvin
Visitor
Visitor

Hi @stephenm ,

 

I was found sysroot folder in image/linux/SDK.

And i following as your step till the end,i can't build the sd data,Debug\sd_card folder even not exist.

圖片_2021-03-03_101240.png

dapulser
Newbie
Newbie

@stephenm 

 

Hi, I am trying to work with your tutorial with ZCU106 but got this error

Screenshot from 2021-03-17 22-54-32.png

but in my vivado design this module exists and i also configured the device tree

Screenshot from 2021-03-17 22-55-35.pngScreenshot from 2021-03-17 22-58-15.png

when creating the petalinux project i used the bsp file by petalinux-create -s so the switches you mentioned in kernel is activated by default thus i did not change any cunfigurations

stephenm
Moderator
Moderator

If you are using the bsp to create the Petalinux project then you would need to use the petalinux-config --get-hw-description=<path to your xsa>.

If you have the axi_gpio_0 added in Vivado, then this will be added the pl.dtsi in the Petalinux project dir.

 

What the error message is saying is that the dtc cannot find the axi_gpio_0 node. To debug such issues, open the device-tree folder in the Petalinux project directory, and search for the missing node. 

dapulser
Newbie
Newbie

@stephenm 

Hello, I tried to debug the device tree and found that pl.dtsi is empty, no axi_gpio related content.

I switched the entire toolchain (Vivado Vitis Petalinux) from 2020.2 to 2020.1 to solve this issue and succeed.

However, another problem occured.

with everything normal, the led just dont work.

I modified the program to debug as follows

Screenshot from 2021-03-24 00-32-51.png

and get the following output 0

Screenshot from 2021-03-24 00-33-53.png

it seems that this area of memory can not be write, and in the vitis memory monitor, if i tried to watch this address i can only got ???????.

Screenshot from 2021-03-24 00-39-09.png

but there is no errors through the whole procedure.

is there any way to debug this issue?

 

 

rickj
Newbie
Newbie
petalinux-build cd images/linux

is not a valid command. Was this supposed to be two lines, or was the 'cd...' not supposed to be there at all?

stephenm
Moderator
Moderator

@rickj Yes, this is two lines.  I have fixed this

stephenm
Moderator
Moderator

@dapulser you can do a devmem to the gpio to see if you can toggle the LED this way. The AXI GPIO register map is seen here:

https://www.xilinx.com/support/documentation/ip_documentation/axi_gpio/v2_0/pg144-axi-gpio.pdf