Introduction

The ability of an embedded system to contain a Graphic User Interface is increasingly important for control, interaction and reporting. A couple of project ago we explored how we could use PYGAME a python frame work for visual game creation.

In this project we are going to explore how we can get QT up and running on the Ultra96 and use that to create GUIs.

As we are close to new year when I do this we will wrap this up with a simple QT application which does a ball drop type of application once started.

PetaLinux Build

To get started with this project we first need to install the PetaLinux 2018.3 tool chain. The reason we are using 2018.3 is that both the Ultra96V1 and Ultra96V2 have PetaLinux board support packages which support this version.

You can download the Ultra96 BSPs here (V1 and V2) while PetaLinux 2018.3 is available here.

Before you run the PetaLinux installer, ensure we have all the necessary packages installed by using the command below.

sudo apt-get install -y gcc git make net-tools libncurses5-dev tftpd zlib1g-dev libssl-dev flex bison libselinux1 gnupg wget diffstat chrpath socat xterm autoconf libtool tar unzip texinfo zlib1g-dev gcc-multilib build-essential libsdl1.2-dev libglib2.0-dev zlib1g:i386 screen pax gzip gawk

Once petalinux 2018.3 is installed we can source the settings.sh script available under the installation directory.

We can then create a new project using the command below depending upon which version of the Ultra96 we are working with.

I had the BSPs within the working directory.

petalinux-create -t project -n ultra96 -s ultra96v1_full_2018_3.bsp

For the Ultra96V2

petalinux-create -t project -n ultra96 -s ultra96v2_oob_2018_3.bsp

Once the project is created the next step is to configure the rootfs, this is the only change needed to the existing BSP to enable support for QT.

Change directory into the project directory just created and use the command

petalinux-config -c rootfs

We will find these under the PetaLinux Package Group identified as packagegroup-petalinux-qt

Selecting the QT packages

Within the package groups petalinux-qt enable packagegroup_petalinux-qt and populate_sdk_qt5 options.

Enabling the QT packages

With these changes completed leave the rootfs configuration dialog and build the petalinux image using the command, this might take a while.

petalinux-build

Once the image has been created, we need to create a boot.bin which can be used. Change directory within the project to /iamges/linux and run the command.

petalinux-package --boot --fsbl zynqmp_fsbl.elf --u-boot u-boot.elf --pmufw pmufw.elf --fpga system.bit

We now have everything we need to create a new SD Card image for the Ultra96. As I use a Virtual machine to be able to access the SD Card from the VM I need create a hard disk definition for the SD Card.

The first thing to do on the host machine is to open a windows command window as administrator and enter the command

wmic diskdrive list brief

This will list all the drives in the machine, as you can see below the SD Card is listed as physical device 2

Knowing the device ID of the SD Card we can then create a hard disk description using the command. This will save the description to the c:\HardDisks folder.

"C:\Program Files\Oracle\VirtualBox\VBoxManage" internalcommands createrawvmdk -filename "c:/HardDisks/sdcard.vmdk" -rawdisk "\\.\PHYSICALDRIVE2"

All that remains then is to add in the new hard disk description to the virtual machine. Close the VM and in the settings tab for the VM add in the new storage.

Select existing disk and add in the SD Card description just created.

Remember to tick the Use HOst I/O Cache description

Re-starting the VM will then show the SD Card and its partitions if they exist. if the partitions do not exist use GParted to create a 500 Mb FAT Boot Partition and a greater than 8 Gb Root partition formatted for Linux.

With the SD Card available we need to do several things

Copy the rootfs.CPIO file over to the root partition

Update the root file system using the rootfs.cpio

Copy the boot.bin and image.ub to the boot partition.

cd ultra96/images/linux

sudo cp rootfs.cpio /media/adiuvo/root

cd /media/adiuvo/root

sudo pax -rvf rootfs.cpio

We can then eject the SD Card and boot the Ultra96, connect to the Ultra96 with a program like WinSCP and explore the file system on the U96.

Under usr/share you will see the qt5 examples directory.

Now we need to set up our Linux environment for creating QT applications. To do this we need a Sys Root for the linux project we just created.

From within the project directory run the commands, note this may take several tens of minutes.

petalinux-build --sdk

petalinux-package --sysroot

With the Sys Root available we are then able to install the QT development environment on our Linux machine or VM.

Installing QT

The version of QT installed installed on the PetaLinux root FS is 5.9.6 from the QT web site download the Linux installer and install the application.

When prompted during the installation process, ensure all of the QT 5.9.6 options are selected.

Along with QT we also need to install a new debugger which we can use to test applications on the target.

In a Linux terminal enter the command

sudo apt-get install gdb-multiarch

Once this has been installed we are ready to configure QT to cross compile and debug for the Ultra96.

The first thing we need to do on the QT Options tab is to select a new QT version on the build and run tab. Select add new and point it to the qmake application it will be available under

<project>/images/linux/sdk/sysrotts.x86_64-petalinux-linux/usr/bin/qt5

On the compilers tab we need to define new C and C++ compilers for the Arm architecture.

On the compilers tab select Add->GCC->C or C++ and then select the correct executable for the cross compilation.

Both will be available under the path

<petalinux install>/tools/linux-i386/aarch64-linux-gnu/bin

Select the following executables

C aarch64-linux-gnu-gcc

C++ aarch64-linux-gnu-c++

Setting the C++ compiler

The penultimate step is to create a new debugger, using the one we just installed, select the Debuggers tab and select Add.

When prompted select Generic Linux Device

This will prompt you for the IP address, log on information and password for the Ultra96.

Once this is completed click next and the connection will be tested for the debugger.

Note if you have issues with the debugger connecting due to availability of a WiFi network the Ultra96 can connect to e.g. a captive portal. we can use a USB thumb drive to transfer the executable from the Host PC to the Ultra 96

The final thing to do is to create a new QT kit, this will pull together everything we have just defined the QT version, Compilers, Debugger and the location of the Sysroot which will be at

<project name>/images/linux/sdk/sysroot/

Close QT

Application Creation

Before we can create a QT application we need to set the environment correctly from a linux terminal run the following commands. The paths below assume the QT installation is in the Home directory.

source <project>/images/linux/sdk/environment-setup-aarch64-xilinx-linux

./Qt5.9.6/Tools/QtCreator/bin/qtcreator

The next step is to create new project, select new project and then select QT Widget Application.

Enter a name of the project

Select the kit you want to create the QT application for, in this instance the MPSoC so the application will be cross compiled for the Arm 64 bit Linux architecture.

Once the project is created select projects option, you will need to provide a project build directory.

You also need to click on the run icon and include the run environment to set the display for :0:0

The final step before we can create the application is to set up the project files we need to define the target file and the target path for the debugger.

Once that is completed we can get started on creating the application. On the design tab we can open the form and start to add in the buttons, boxes, and other layout elements we desire.

We can customize the objects which are added, using the property viewer on bottom right hand side.

The application itself does the following

On start up it loads a JPG image into a label and configures a timer

It uses a vertical slider to represent the ball drop, the slider has a min value of 0 and a max value of 100.

There are also two labels which will be used to display images when the count down is reached.

When the button is clicked the timer is started to generate events at one second intervals

In the final 10 seconds the counter moves the slider towards the bottom of the screen to mimic a ball drop.

When the slider hits the bottom pictures and text for happy new year are show on the screen.

All of the images need to be located in the directory of the Ultra96 from which the application is run from.

#ifndef MAINWINDOW_H

#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {

class MainWindow;

}

class MainWindow : public QMainWindow

{

Q_OBJECT

public:

explicit MainWindow(QWidget *parent = 0);

~MainWindow();

private slots:

void on_pushButton_clicked();

void on_pushButton_2_clicked();

private:

Ui::MainWindow *ui;

int timer;

protected:

void timerEvent(QTimerEvent *event);

};

#endif // MAINWINDOW_H

The main body of the application can be seen below

#include "mainwindow.h"

#include "ui_mainwindow.h"

//#include <QSlider>

#include <QTimer>

MainWindow::MainWindow(QWidget *parent) :

QMainWindow(parent),

ui(new Ui::MainWindow)

{

ui->setupUi(this);

QPixmap image("adiuvo.jpg");

ui->label_3->setPixmap(image);

}

MainWindow::~MainWindow()

{

delete ui;

}

void MainWindow::timerEvent(QTimerEvent *event)

{

int count=0;

count = ui->verticalSlider->value();

ui->verticalSlider->setValue(count+=10);

if(ui->verticalSlider->value()+1>ui->verticalSlider->maximum()){

ui->label_2->setText("HAPPY NEW YEAR!!!");

QPixmap image("new-years-eve.jpg");

ui->label_4->setPixmap(image);

}

}

void MainWindow::on_pushButton_2_clicked()

{

timer = startTimer(1000);

}

A simple video of the application running can be seen here

We now have a system on which we can create GUIs which enable interaction with the Ultra96. I will come back to this system in my blog to demonstrate how we can use QT with peripherals in the PL for control and reporting.

See previous projects here.

Additional information on Xilinx FPGA / SoC development can be found weekly on MicroZed Chronicles.