How to Setup STM32MP1 with Qt

The need for complex graphics and communication stacks in modern embedded projects has grown exponentially. WIFI, Bluetooth and MIPI are just a few examples that come to mind. This is where embedded linux thrives. If the extra costs can be absorbed, the use of embedded Linux will save tons of hours in development time for stacks like these. There are tons of embedded linux boards but one great option for graphical applications is the STM32MPU series. This tutorial will show how to setup STM32MP1 with Qt. The STM32MPU series is a great choice for embedded linux projects, specifically with graphics applications. The STM32MPU has decent documentation, contains a M4 co-processor which is great for offloading time sensitive computing and supports 2 lane MIPI DSI.

The first half of this tutorial walks through the setup of the st-example-image-qt Distribution Package with the STM32MP157c-DK2 development kit. The second half outlines how to set up cross compilation in order to deploy Qt projects directly from a host Linux machine to the embedded target using qtcreator. The st-example-image-qt image is not officially supported by ST and therefore has some bugs / work arounds to get fully setup. My hope is to create the most comprehensive guide that outlines all the tips, tricks and workarounds to get this image up and running. By no means am I an expert in Yocto but I spent enough time and frustration getting this board running with Qt that I needed to share it if not for my own future reference. Let’s get started.

 

GIF of analog speedometer with needle moving

 

Part 1:

Prerequisites:

I used virtual machine running Ubuntu 18.04 with 5.5GB of RAM, 85GB of storage and 3.5GB of swap memory allocated. You will likely need close to 50GB of free space and will need your RAM/memory allocation to look very similar to mine (~8GB) at a minimum. With these specs, the image build took upwards of 15 hours…

First, the Starter Package will need to be installed on the board. This is to prove that your board boots correctly, populates all the flash Partitions that you will also use for the Distribution Package and introduces you to the STM32CubeProgrammer tool. If you do not have the Starter Package installed, follow this article: Getting Started with STM32MP157c-DK2.

Second run the following commands in your host computer terminal to install a couple of support packages that Yocto and OpenEmbedded need.

host:~$ sudo apt-get udpate
host:~$ sudo apt-get install gawk wget git-core diffstat unzip texinfo gcc-multilib build-essential chrpath socat cpio python python3 python3-pip python3-pexpect xz-utils debianutils iputils-ping
host:~$ sudo apt-get install libsdl1.2-dev xterm
host:~$ sudo apt-get install make xsltproc docbook-utils fop dblatex xmlto
host:~$ sudo apt-get install python-git
host:~$ sudo apt-get install repo
host:~$ sudo apt-get install coreutils bsdmainutils sed bc lrzsz corkscrew cvs subversion mercurial nfs-common nfs-kernel-server libarchive-zip-perl dos2unix texi2html diffstat libxml2-utils

 

Step 1 — Initialize Repo:

If you are following the ST recommended file system organization (which I recommend), create the following directory where you would like to install the Distribution package:

host:~$ cd STM32MPU_workspace/STM32MP15-Ecosystem-v1.2.0
host:~$ mkdir Distribution-package
host:~$ cd Distribution-package
host:~$ mkdir openstlinux-4.19-thud-mp1-19-02-20
host:~$ cd openstlinux-4.19-thud-mp1-19-02-20

Now initialize the repo in the newly created directory.

host:~$ repo init -u https://github.com/STMicroelectronics/oe-manifest.git -b refs/tags/openstlinux-4.19-thud-mp1-19-02-20
host:~$ repo sync

You might see a couple warnings when running the sync but it should be fine as long as you have the repo tool installed from the prerequisites section.

 

Step 2 — Modifying Yocto Files:

There are a couple Yocto files we are going to edit in order to remove some problem packages that we don’t need. We’ll also add some Qt eglfs configurations to a script so that we don’t have to manually set them every time we want to run an application on our target board.

while in the “openstlinux-4.19-thud-mp1–19–02–20” directory, navigate to the following directory.

host:~$ cd layers/meta-st/meta-st-stm32mp/conf/machine/include

Open the following file using whatever editor you prefer (such as nano or vim).

host:~$ nano st-machine-common-stm32mp.inc

Remove lines 141, 149 and 150

openocd-stm32mp-native \
nativesdk-openocd-stm32mp \
nativesdk-sdcard-raw-tools \

Save the file and exit your editor. Next, from the “openstlinux-4.19-thud-mp1–19–02–20” directory, navigate to the following directory and open the following file.

host:~$ cd layers/meta-st/meta-st-openstlinux/recipes-qt/qt5/files
host:~$ nano qt-eglfs.sh

Add then following two lines to the file after “export QT_QPA_PLATFORM=eglfs”.

export QT_QPA_EGLFS_ALWAYS_SET_MODE="1"
export QT_QPA_EGLFS_INTEGRATION="eglfs_kms"

Lastly, we need to fix a bug related to the rootfs size for the image. The default Weston image only needs 786MB for the rootfs partition but the Qt image needs 1.1GB so we need to update this. Navigate to the following directory and open the given file using whatever editor you like.

host:~$ cd layers/meta-st/conf/machine/include
host:~$ nano st-machine-common-stm32mp.inc

Under the Image section, change the following lines:

# New value proposed for rootfs is 768MB
ROOTFS_PARTITION_SIZE = “768432”

To:

ROOTFS_PARTITION_SIZE = “1400000”

 

Step 3 — Build Image:

Now we are ready to start the image build process. As stated earlier, make sure you have close to 8GB of memory (RAM + swap file or partition), about 50GB of storage and 10–15 hours to spare not using your computer. Make sure your computer is plugged into power and has good fan ventilation.

Navigate back to the “openstlinux-4.19-thud-mp1–19–02–20” directory and run the following command and accept any necessary agreements.

host:~$ DISTRO=openstlinux-eglfs MACHINE=stm32mp1 source layers/meta-st/scripts/envsetup.sh

This will set up bitbake and automatically move you into a new sub directory called “build-openstlinuxeglfs-stm32mp1”. Now before building the actual image there are a few things to review. There are a couple of packages that are large and take up a lot of memory, specifically the qtwebkit package. In order to get through the build it may be necessary to use the -k option with bitbake (which continues to build the image, even if a package fails), increase your RAM or swap size if possible and re-run bitbake command multiple times. I recommend starting off using the -k option with bitbake just so you do not have to babysit the build and it will continue to run if a certain package fails. Execute the following command:

host:~$ bitbake -k st-example-image-qt

NOTE: If you for some reason have to manually stop the build, press “control+c” and let the current process finish running (which could take ten minutes or more). This will save your build state and you won’t have to re-run the whole thing. Do not keep pressing “control+c” or you will corrupt the build and have to start from scratch.

What to do if the build failed:

It is okay to have warnings when the build completes but we do not want any errors. Don’t worry if the build gives errors and is incomplete at this stage. The next time you re-run the bitbake command, it will only try to build the packages that failed which should free up some memory. First try running the same bitbake -k command again. If that does not work, try running the qtwebkit package by itself with the following command:

host:~$ bitbake qtwebkit

If this does not work, try adding more swap memory to your swap file or swap partition (which I had to do and needed about 3.5GB of swap memory + 5.5GB of allocated RAM). Lastly, if that does not work (it should if you make your swap file large enough) then you can try following additional steps outlined in this article, Yocto+QT5/B2QT build fails. Also note that if you run out of storage when running this commands multiple times then you can free up some space by navigating to the following directory and deleting the tmp-glibc directory before re-running.

host:~$ cd ~/STM32MPU_workspace/STM32MP15-Ecosystem-v1.2.0/Distobution-package/openstlinux-4.19-thud-mp1-19-02-20/build-openstlinuxeglfs-stm32mp1
host:~$ rm -rfv tmp-glibc

 

Step 4 — Flashing the Image:

One the build completes with no errors, the STM32CubeProgrammer tool is used to flash the image to the board. The STM32CubeProgrammer should have been installed when setting up the Starter Package in the prerequisites section.

First, verify that the image was created by navigating to the following directory:

host:~$ cd STM32MPU_workspace/STM32MP15-Ecosystem-v1.2.0/Distribution-package/openstlinux-4.19-thud-mp1-19-02-20/build-openstlinuxeglfs-stm32mp1/tmp-glibc/deploy/images/stm32m1/flashlayout_st-example-image-st/flashlayout_st-example-image-qt

Verify that the following file exists in this directory:

FlashLayout_sdcard_stm32mp157c-dk2-trusted.tsv

If this file exists then your image was built and we are ready to upload it to the board. If the ST recommended file organization was used to set up the Starter Package then the STM32CubeProgrammer should be installed in the following location:

~/STM32MPU_workspace/STM32MPU-Tools/STM32CubeProgrammer-x.y.z/bin/STM32_Programmer_CLI

Before we flash the image, the two dip switches on the back of the board need to be switched to the “off” position to enable flashing.

STM32MP157c-DK2 boot switches

Plug the board’s “USB” port into the computer and power the board on. Navigate back to the image folder and use the following command in order to flash the image to the board. This will take about five minutes to complete and you might have to run the command twice as the board tries to reboot and loses connection the first time.

host:~$ cd STM32MPU_workspace/STM32MP15-Ecosystem-v1.2.0/Distribution-package/openstlinux-4.19-thud-mp1-19-02-20/build-openstlinuxeglfs-stm32mp1/tmp-glibc/deploy/images/stm32m1
host:~$ sudo ~/STM32MPU_workspace/STM32MPU-Tools/STM32CubeProgrammer-x.y.z/bin/STM32_Programmer_CLI -c port=usb1 -w flashlayout_st-example-image-qt/FlashLayout_sdcard_stm32mp157c-dk2-trusted.tsv

NOTE: If the flash fails and you get a “Request would exceed designated area!” message on the board’s DSI display, then make sure you completed the last section of Step 2.

NOTE: You can add the CubeProgrammer to your PATH and not have to reference the whole path each time you run the command but I could not get it to work for some reason so just used the full path instead of wasting more time troubleshooting.

Power off your board and move the dip switches on the back to the “on” position. Plug your board back into power and you should see the STM32 boot screen appear after a few seconds. A few seconds later you should see the STM32 splash screen appear. I had issues trying to ssh into the board via Ethernet directly from the board to my computer but if I plugged the board into my router it worked fine.

 

Step 5 — Run Sample QT Display:

The st-example-image-qt should be fully installed on your board! To run a Qt example, ssh into your board and execute the following commands to turn off the backsplash image, navigate to the examples directory and run an example.

target:~$ psplash-drm-quit
target:~$ cd /usr/share/examples/opengl/hellowindow 
target:~$ ./hellowindow

Next, we’ll learn how to setup the Qt tool chain, qtcreator and enable cross compilation in order to deploy Qt projects directly to your board from your Linux host computer.

 

Part 2:

In this part two of the tutorial I will explain how to set up the meta-qt5 toolchain, cross compilation and Qt creator in order to deploy Qt applications to a target STM32MP157c-DK2 from a linux host machine. If you do not have the st-example-image-qt set up on your board, please refer to part one before continuing on. I decided to create this part 2 section because I found setting up cross compilation difficult and online resources limited.

 

Prerequisites:

If you are almost out of storage after completing Part 1 then delete the tmp folder in the following location.

host:~$ cd ~/STM32MPU_workspace/STM32MP15-Ecosystem-v1.2.0/Distobution-package/openstlinux-4.19-thud-mp1-19-02-20/build-openstlinuxeglfs-stm32mp1
host:~$ rm -rfv tmp-glibc

 

Step 1 — Set Up Environment and bitbake:

Before building the meta-qt5 toolchain, one of the recipe files needs to be edited else a qmlcachegen error will appear during compilation. Navigate to the following directory and open the specified file with your editor of choice.

host:~$ cd ~/STM32MPU_workspace/STM32MP15-Ecosystem-v1.2.0/Distobution-package/openstlinux-4.19-thud-mp1-19-02-20/layers/meta-qt5/recipes-qt/packagegroups
host:~$ nano nativesdk-packagegroup-qt5-toolchain-host.bb

Add “nativesdk-qtdeclarative-tools \” to the file under the section titled, “RDEPENDS_${PN} += “ \”. The entire file should appear as follows.

# Copyright (C) 2014 O.S. Systems Software LTDA. 
SUMMARY = "Host packages for the Qt5 standalone SDK or external toolchain"
LICENSE = "MIT"

inherit nativesdk packagegroup

PACKAGEGROUP_DISABLE_COMPLEMENTARY = "1"

RDEPENDS_${PN} += " \
    nativesdk-packagegroup-sdk-host \
    nativesdk-qttools-tools \
    nativesdk-qtbase \
    nativesdk-qtdeclarative-tools \
    nativesdk-perl-modules \
"

Next, the environment setup script will have to be ran. Navigate to the following directory and run the following command.

host:~$ cd ~/STM32MPU_workspace/STM32MP15-Ecosystem-v1.2.0/Distobution-package/openstlinux-4.19-thud-mp1-19-02-20/build-openstlinuxeglfs-stm32mp1
host:~$ DISTRO=openstlinux-eglfs MACHINE=stm32mp1 source layers/meta-st/scripts/envsetup.sh

That will setup bitbake and automatically move you into a new sub directory called “build-openstlinuxeglfs-stm32mp1”. Now the meta-qt5 toolchain can be built by running the following command.

host:~$ Bitbake meta-toolchain-qt5

The bitbake command should take 10 — 20 minutes to complete.

NOTE: If the bitbake fails due to qtwebkit, navigate to the following directory and open the specified file with your editor of choice.

host:~$ cd ~/STM32MPU_workspace/STM32MP15-Ecosystem-v1.2.0/Distobution-package/openstlinux-4.19-thud-mp1-19-02-20/layers/meta-st/meta-st-openstlinux/recipes-qt/packagegroups
host:~$ nano packagegroup-qt5-toolchain-target.bbappend

Add the following section above the “RDEPENDS_${PN}_remove += “\” section.

USE_WEBENGINE = " \
    qtwebengine-dev \
    qtwebengine-mkspecs \
    qtwebengine \
"

Add the following lines of code to the end of the “RDEPENDS_${PN}_remove += “\” seciton.

qtwebkit-dev \ 
qtwebkit-mkspecs \ 
qtwebkit-qmlplugins \

The whole file should now look like the following.

USE_WEBENGINE = " \
    qtwebengine-dev \
    qtwebengine-mkspecs \
    qtwebengine \
"
RDEPENDS_${PN}_remove += "\
    qtenginio-dev \
    qtenginio-mkspecs \
    ${@bb.utils.contains('DISTRO_FEATURES', 'opengl', 'qtenginio-qmlplugins', '', d)} \
    ${@bb.utils.contains('DISTRO_FEATURES', 'x11', '${USE_X11}', '', d)} \
    qtwebkit-dev \
    qtwebkit-mkspecs \
    qtwebkit-qmlplugins \
"

Re run the bitbake command.

 

Step 2 — Install the SDK:

Now that the toolchain is installed, the SDK can also be installed. Navigate to the following directory and run the SDK installation script.

host:~$ cd ~/STM32MPU_workspace/STM32MP15-Ecosystem-v1.2.0/Distobution-package/openstlinux-4.19-thud-mp1-19-02-20/build-openstlinuxeglfs-stm32mp1/tmp-glibc/deploy/sdk
host:~$ ./meta-toolchain-qt5-openstlinux-eglfs-stm32mp1-x86_64-toolchain-2.6-snapshot.sh

Accept all the agreements and choose the default installation path. The installation should take about ten minutes.

Once the SDK is installed, there are some OpenGL for Embedded Systems (GLES) library files that we will need to copy from the board image to the Linux host as the SDK install does not pull the correct versions. Navigate to the following directory on the Linux host computer and remove the following library files with broken links. The files to be removed should appear in red text.

host:~$ cd /opt/st/stm32mp1/2.6-snapshot/sysroots/cortexa7t2hf-neon-vfpv4-openstlinux_eglfs-linux-gnueabi/usr/lib 
host:~$ rm -rfv libVSC.so
host:~$ rm -rfv libGLESv2.so
host:~$ rm -rfv libGLESv2.so.2 
host:~$ rm -rfv libGAL.so

Now power on the STM32MP157c-DK2 board in order to copy the correct library files that we just deleted from the board to the host computer. With the board powered on and using your board’s specific IP address, execute the following commands to copy the libraries over.

host:~$ sudo scp root@192.168.X.XXX:/usr/lib/libVSC.so /opt/st/stm32mp1/2.6-snapshot/sysroots/cortexa7t2hf-neon-vfpv4-openstlinux_eglfs-linux-gnueabi/usr/lib/libVSC.so
host:~$ sudo scp root@192.168.X.XXX:/usr/lib/libGLESv2.so /opt/st/stm32mp1/2.6-snapshot/sysroots/cortexa7t2hf-neon-vfpv4-openstlinux_eglfs-linux-gnueabi/usr/lib/libGLESv2.so
host:~$ sudo scp root@192.168.X.XXX:/usr/lib/libGLESv2.so.2 /opt/st/stm32mp1/2.6-snapshot/sysroots/cortexa7t2hf-neon-vfpv4-openstlinux_eglfs-linux-gnueabi/usr/lib/libGLESv2.so.2 
host:~$ sudo scp root@192.168.X.XXX:/usr/lib/libGAL.so /opt/st/stm32mp1/2.6-snapshot/sysroots/cortexa7t2hf-neon-vfpv4-openstlinux_eglfs-linux-gnueabi/usr/lib/libGAL.so

Next, we need to restart the terminal so that we can run the environment setup script for the SDK. After opening a new terminal session, run the following script.

host:~$ . /opt/st/stm32mp1/2.6-snapshot/environment-setup-cortexa7t2hf-neon-vfpv4-openstlinux_eglfs-linux-gnueabi

NOTE: You will need to run this setup script every time you open Qt creator.

With the correct libraries in place and the environment setup script ran, it is time to install and setup qtcreator.

 

Step 3 — Install qtcreator:

I recommend installing Qt creator from the binary downloaded from their website instead of using sudo apt-get because it will make it easier to find all the files associated with qtcreator. On top of this, the binary includes a uninstall script that makes it much easier to ensure qtcreator is completely removed if the time comes. In a web browser, go to the Qt Open Source Downloads page located here, Qt Downloads page and download the Linux installer package. Now navigate to your downloads folder on your Linux host and execute the following command to make the file executable.

host:~$ cd Downloads 
host:~$ chmod a+x qt-unified-linux-x64-X.X.X-online.run

Once the file is executable, run the installer and follow the prompts to install whichever version of qtcreator you need. This needs about 10 GB and takes around ten minutes.

host:~$ ./ qt-unified-linux-x64-X.X.X-online.run

NOTE: Be sure to open qtcreator from the terminal and not your applications otherwise certain dependencies will not get loaded. The qtcreator executable can be found where you set your qtcreator path during the installation at the following location.

Qt/Tools/QtCreator/bin/qtcreator

 

Step 4 — Configure qtcreator for Cross Compilation:

With qtcreator installed on your host machine we can now set up cross compilation. Instead of re-inventing the wheel, I found this YouTube tutorial to be very helpful in demonstrating how to set this up. The relevant part of the video is from minute 27.26 and on and can be found here, Beaglebone: Qt Creator for C++ ARM Embedded Linux Development. Note that this video does demonstrate the setup for a Beaglebone Black and the Angstrom toolchain but the same principals apply to the STM32MP157C-DK2 board and it is relatively easy to follow.

In case you are confused where to find the compiler and debugger in our meta-qt5 Sysroot directories, I have described each one below.

Compiler:

/opt/st/stm32mp1/2.6-snapshot/sysroots/x86_64-openstlinux_eglfs_sdk-linux/usr/bin/arm-openstlinux_eglfs-linux-gnueabi/arm-openstlinux_eglfs-linux-gnueabi-gcc

Debugger:

/opt/st/stm32mp1/2.6-snapshot/sysroots/x86_64-openstlinux_eglfs_sdk-linux/usr/bin/arm-openstlinux_eglfs-linux-gnueabi/arm-openstlinux_eglfs-linux-gnueabi-gdb

NOTES:

Under “Kits” in qtcreator, the “Qt version” field needs to have an input to the qmake located in the following directory. You will most likely have to manualy enter this in the “Qt Versions” tab.

/opt/st/stm32mp1/2.6-snapshot/sysroots/x86_64-openstlinux_eglfs_sdk-linux/usr/bin/qmake

Lastly, when completing the “Device” field for the STM32MP157c-DK2 board, it may look different then in the video depending on your Qt verison. In some versions, you are able to enter in the ip address for ssh and the root password and in others, you have to use the “Create New” button in the “Private key file:” section. Both methods should work fine.

 

Step 5 — Final Setup and Testing:

While these steps are described in the video linked in section 4, I am going to reiterate them here. To test our cross compilation setup, follow these steps. Ensure that the environment setup scripts was run before opening qtcreator.

host:~$ . /opt/st/stm32mp1/2.6-snapshot/environment-setup-cortexa7t2hf-neon-vfpv4-openstlinux_eglfs-linux-gnueabi

Also make sure that the qtcreator session you have open was opened from the terminal (See note in step 3).

Select a new project and click on “Qt Quick Application — Empty”. Name the project and put it in a projects directory somewhere convenient. Next select qmake as the build system and your Kit you just set up in step 4. Once created, open the “Design” tab located on the left hand side and add in a simple text box for testing purposes. Next, within the project, open the file named “main.qml” and change the window height and width to the correct screen size (480X800).

Finally, within the project, open the .pro file and edit the section titled “Default rules for deployment”. Comment out all logic to do with target.path and enter in the custom path that we want to deploy to. The final result should look like the following.

# Default rules for deployment.
TARGET = stm32mp1Test
    target.files = stm32mp1Test
    target.path = /home/root
INSTALLS += target

#qnx: target.path = /tmp/$${TARGET}/bin
#else: unix:!android: target.path = /opt/$${TARGET}/bin
#!isEmpty(target.path): INSTALLS += target

Now everything on the qtcreator side should be ready for testing. Power on the STM32MP157c-DK2. SSH into the board and run the following command in order to turn off the default backsplash image.

target:~$ psplash-drm-quit

Exit out of the SSH session and go back to qtcreator. On the left hand side above the Run button, make sure that “Profile” is selected under the monitor symbol. Click the run play button and you should see the text box deployed to the STM32MP1 board. You may have to click run twice. Now when you SSH into your board you should see your project executable located in the root directory.

Check out my diy speedometer project to see what Qt can do!

DIY Digital Speedometer – Phase One

Thanks for reading!

 

If you found this content interesting or useful, buy me a coffee!

Bitcoin Wallet: 

bc1q0vkx34w5y4yt5nq38a4rvk7gvgnxm2xv5lvyft

 

References:

Helpful Tutorials:
Helpful Forum Posts:

Related Articles

Leave a Comment

Your email address will not be published. Required fields are marked *

Braden Sunwold

Embedded Firmware Engineer

I love working on the boarder between software and hardware and creating devices that interact with the physical world.

Explore
Donate Now
Love BNE?

Donations like your's keep killer content coming