On this page

C

Using Qt Quick Ultralite with Zephyr

Zephyr is an RTOS for embedded systems. It provides a fully preemptible tickless kernel, both cooperative and preemptive threading, semaphores and queues.

Note: This is the recommended workflow for new Qt Quick Ultralite Zephyr applications, where Qt Quick Ultralite is added as a west module. For the workflow where the application is exported as a standalone Zephyr project, see Manual Qt Quick Ultralite integration with Zephyr.

Qt Quick Ultralite offers tools which enable easy integration with a pre-existing Zephyr project. The Qt Quick Ultralite Zephyr module is a west module that runs qmlprojectexporter during the Zephyr CMake configure step, maps the Zephyr board to a Qt Quick Ultralite platform, and adds the generated sources to the build as a Zephyr library. The module is configured through Kconfig and provides the west build-qul-libs command for building the Qt Quick Ultralite target libraries.

Supported architectures, platforms and Zephyr versions

Qt Quick Ultralite supports the following hardware:

Hardware boardMCUArchitectureCompilerSupported Zephyr version
NXP IMXRT1060-EVKBMIMXRT1062DVL6BARM Cortex-M7Zephyr SDK 1.0.1 (arm-zephyr-eabi GCC)4.4.0
NXP IMXRT1064-EVKMIMXRT1064DVL6AARM Cortex-M7Zephyr SDK 1.0.1 (arm-zephyr-eabi GCC)4.4.0

In addition, Qt Quick Ultralite supports Zephyr's host-based simulator board, which runs Zephyr as an application on the development host:

BoardHostArchitectureCompilerSupported Zephyr version
native_simLinuxx86_64GNU Compiler Collection (GCC)4.4.0

Prerequisites

You need to install the following prerequisites to start working with the Qt Quick Ultralite Zephyr module:

  • Qt for MCUs 2.12.3
  • Qt Quick Ultralite platform package (see supported platforms)
  • Zephyr 4.4.0
  • A toolchain for the target:
    • Zephyr SDK 1.0.1
    • GNU Compiler Collection (GCC) for native_sim
  • CMake 3.21.1 or newer
  • Ninja 1.10.0 or newer
  • Python 3.12 or newer

Workflow

The overall workflow for creating and compiling a Qt Quick Ultralite application is as follows:

Workflow for creating, building, and flashing a Qt Quick Ultralite application with the Qt Quick Ultralite Zephyr module, looping back to rebuild after application changes.

Setting up a new application

This section covers setting up the Zephyr application that runs Qt Quick Ultralite. To create the Qt Quick Ultralite application, see Qt Design Studio on MCUs documentation.

Creating a Zephyr application directory

Qt Quick Ultralite runs in a Zephyr thread of its own that the Zephyr application creates. The thread runs the Qt Quick Ultralite event loop through Qul::Application::exec() and is self-contained; the rest of the Zephyr application runs alongside it. The application that creates the thread consists of a CMakeLists.txt file, a prj.conf file, and the application sources.

Create a directory for the west workspace, and the application directory app with its src subdirectory under it:

mkdir myproject
cd myproject
mkdir -p app/src
mkdir myproject
cd myproject
mkdir app\src

Obtaining the Qt Quick Ultralite Zephyr module repository

The Qt Quick Ultralite Zephyr module is distributed as a git bundle file included in the Qt Quick Ultralite installation:

<QT_INSTALL>/QtMCUs/2.12.3/platform/boards/zephyr/qtultralight-zephyr-module.bundle

Use the bundle to create a local copy of the module repository, then make that copy available from a git server that your west workspace can reach:

git clone --origin bundle <path/to/qtultralight-zephyr-module.bundle> qtultralight-zephyr-module
cd qtultralight-zephyr-module
git branch -m main
git remote add origin <your-git-server-url>/qtultralight.git
git push origin main

Use the same server URL as the url-base value for the qt remote in app/west.yml, which is created in the next step.

Each Qt Quick Ultralite release includes an updated bundle. To move to a new Qt Quick Ultralite version, repeat these steps with the bundle from that release and update the copy on your git server. Then run west update in existing west workspaces to pull the new commit.

Creating app/west.yml

These steps keep the west manifest in the application directory, which makes app the manifest repository as well. A manifest repository that is separate from the application works the same way. For the workspace topologies that west supports, see west workspaces.

Create the west manifest in app/west.yml. Set url-base for the qt remote to the git server URL you pushed the Qt Quick Ultralite Zephyr module repository to in the previous step. Add the Qt Quick Ultralite Zephyr module as a project in it, with import: true so that west also reads the module's own manifest, which declares the build-qul-libs extension command:

manifest:
  remotes:
    - name: zephyrproject-rtos
      url-base: https://github.com/zephyrproject-rtos
    - name: qt
      url-base: https://your.git.server/path

  projects:
    - name: zephyr
      remote: zephyrproject-rtos
      revision: v4.4-branch
      import: true

    - name: qtultralight
      remote: qt
      repo-path: qtultralight.git
      revision: main
      path: qtultralight
      import: true

  self:
    path: app

The repository that the qtultralight project points to is a thin wrapper. It contains only the Zephyr integration: the Kconfig definitions, the Zephyr CMake files, and the west build-qul-libs command. Qt Quick Ultralite itself is not part of it, so west update clones the wrapper alone.

The host tools such as qmlprojectexporter, the platform sources, and the target libraries come from a Qt Quick Ultralite installation that is kept outside the west workspace. The module locates that installation through QUL_ROOT.

Initializing and updating the workspace

west init -l app
west update

Creating app/CMakeLists.txt

Create a simple CMakeLists.txt file in app/ that lists the application sources:

cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(myapp)

target_sources(app PRIVATE src/qul_main.cpp)

Note: If the QML project uses C++ interfaces or models, add the source files to target_sources as well. Their headers are made available to qmlprojectexporter with CONFIG_QUL_INCLUDE_DIRS.

The generated project also includes the platform port's zephyr-linker-sources.cmake, which adds the Qt Quick Ultralite linker sections to the Zephyr-generated linker script.

Creating app/prj.conf

Create app/prj.conf to enable the module and point it at the qmlproject file:

CONFIG_QUL=y
CONFIG_QUL_QMLPROJECT_FILE="path/to/your/qul_application.qmlproject"

CONFIG_QUL_QMLPROJECT_FILE accepts an absolute path, a path relative to the application directory, or a path starting with ~.

These two options are the minimal configuration. See the Kconfig reference for a full list of Qt Quick Ultralite specific Kconfig values.

Creating app/src/qul_main.cpp

Create the application entry point in app/src/qul_main.cpp. This source file provides the thread that runs Qt Quick Ultralite. The QML root item header is generated from the .qmlproject file at build time and is available on the include path automatically:

#include "MainScreen.h"

#include <qul/application.h>
#include <qul/qul.h>
#include <zephyr/kernel.h>

#define QUL_THREAD_STACK_SIZE 16384
#define QUL_THREAD_PRIORITY   5

static void qul_thread_entry(void *, void *, void *)
{
    Qul::initHardware();
    Qul::initPlatform();

    Qul::Application app;
    static MainScreen item;
    app.setRootItem(&item);
    app.exec();
}

K_THREAD_DEFINE(qul_tid, QUL_THREAD_STACK_SIZE,
                qul_thread_entry, NULL, NULL, NULL,
                QUL_THREAD_PRIORITY, 0, 0);

K_THREAD_DEFINE creates the Zephyr thread at boot. The thread entry point initializes the hardware and the platform before it starts the Qt Quick Ultralite event loop.

Note: MainScreen assumes the main qml file in your Qt Quick Ultralite application is MainScreen.qml. Change the item name to match the main qml filename in your application.

Note: The stack size depends on the complexity of the Qt Quick Ultralite application. The example value here is sufficient for the Qt Quick Ultralite Thermostat Demo.

Note: native_sim calls posix_exit() when the display window is closed, which may crash an application that uses the thread code above. On native_sim, use the native_sim specific application thread instead.

Setting QUL_ROOT

The Qt Quick Ultralite Zephyr module requires a Qt for MCUs installation to work. Set the QUL_ROOT environment variable to the installation directory, so that the module finds the host tools, the platform sources, and the libraries:

export QUL_ROOT=$HOME/Qt/QtMCUs/2.12.3
set QUL_ROOT=C:\Qt\QtMCUs\2.12.3

You can also set QUL_ROOT by passing it to the west build command, after --:

west build -b <board> app -- -DQUL_ROOT=$HOME/Qt/QtMCUs/2.12.3
west build -b <board> app -- -DQUL_ROOT=C:\Qt\QtMCUs\2.12.3

Note: The value that is passed on the command line takes precedence over the QUL_ROOT environment variable.

Configuration

The Qt Quick Ultralite Zephyr module adds Kconfig options that configure how Qt Quick Ultralite is built into the Zephyr application. Set the options in the application's prj.conf, or through the interactive Kconfig interface:

west build -b <board> app -t menuconfig

Where <board> is the Zephyr board target and -b is the short form of --board. The menuconfig target runs the CMake configure step, which needs the board target. Once the build directory exists, west reuses the board from the CMake cache and you can leave out -b <board>.

Note: CONFIG_QUL, CONFIG_QUL_DEFAULT_CONF and CONFIG_QUL_DEVICELINK must be set in prj.conf. The module reads them before Kconfig runs, so setting them only through menuconfig does not take effect.

The Qt Quick Ultralite options are under Modules > qtultralight. Changes are saved to build/zephyr/.config and take effect on the next west build. For the complete list of options, see the Kconfig reference.

The Qt Quick Ultralite application itself is configured in its .qmlproject file and in the platform's BoardDefaults_*.qmlprojectconfig file, see QmlProject manual and Defining default variables for the platform. The module locates the Qt Quick Ultralite installation and the platform sources through CMake variables and environment variables, see CMake variable reference and Environment variable reference.

Building

By default, Qt Quick Ultralite uses the prebuilt libraries from the installation. To build the libraries yourself, see Building the Qt Quick Ultralite libraries.

Build the application by running west build with the target board:

west build -b <board> app

Where <board> is the Zephyr board target. For the board target to use, see the board-specific page listed in Supported architectures, platforms and Zephyr versions.

The module maps the board target to a Qt Quick Ultralite platform through the QUL_ZEPHYR_BOARDS variable. Each platform port lists the board targets that it supports in its zephyr-boards.cmake file, and the module selects the port whose list contains the board target verbatim.

Rebuilding after changes

When you change the QML files or the .qmlproject file of the Qt Quick Ultralite application, you only need to rebuild the Zephyr project. qmlprojectexporter automatically re-exports the Qt Quick Ultralite application if any changes are detected.

Note: Changes to QML files are picked up automatically. If you change BinaryFiles, font files, translation files, or image resources without changing any QML file, run west build -t rebuild_cache to re-run the CMake configure step and regenerate the application sources.

Flashing

For hardware boards, flash the built application with west:

west flash

Building the Qt Quick Ultralite libraries

By default, Qt Quick Ultralite uses the prebuilt libraries from the installation, which are built in the MinSizeRel or Release configuration. To build your own libraries, run west build-qul-libs. The following example builds them in the Debug configuration:

west build-qul-libs --board <board> --build-type Debug

Where <board> is the Zephyr board target, the same value as for west build.

Note: Pass --build-type when the application selects CONFIG_QUL_BUILD_TYPE_PLATFORM_DEFAULT, which specifies no build type, or when the Zephyr .config does not exist yet.

The command builds the Qt Quick Ultralite platform and core libraries and installs them into <build-dir>/qul_install. It does not build the application. After the libraries are installed, the command reconfigures the Zephyr build directory so that the next west build picks up the new libraries.

The command supports the following options:

OptionDescription
--board, -bThe Zephyr board to build the libraries for. Falls back to the BOARD environment variable when omitted.
--build-dir, -dThe Zephyr build directory that the libraries are built into and installed under. Defaults to build relative to the west workspace root.
--build-typeThe CMake build type: Debug, Release, RelWithDebInfo, or MinSizeRel. Read from CONFIG_QUL_BUILD_TYPE in the Zephyr .config when that option selects an explicit build type. The command stops with an error when neither names one.

Use this option to override the library build type. It applies to the library build only. The build type is part of the library file names, so libraries of several build types can live side by side in the same installation.

The application build looks for the build type that CONFIG_QUL_BUILD_TYPE selects, or that the platform metadata declares. Match that build type to link the application against the libraries that you build here.

--jobs, -jThe number of parallel build jobs. Defaults to the host CPU count.
--qul-rootThe path to the Qt Quick Ultralite installation that contains the platform sources, toolchain files, and host tools.
--platform-boards-dirThe directory that contains the Qt Quick Ultralite platform board sources, for example <path/to/qul>/platform/boards. Falls back to the QUL_PLATFORM_BOARDS_DIR environment variable, and then to <qul-root>/platform/boards.

The build directory is expected to be configured for the same board as the library build. If --board does not match the board recorded in the build directory, the command stops with an error.

Note: The command reads the Kconfig options from <build-dir>/zephyr/.config, which does not exist until the Zephyr build has been configured once. On a fresh workspace, run west build first, then west build-qul-libs, and then west build again. Without that file, the CONFIG_QUL_* options take their default values, regardless of the application's prj.conf.

DeviceLink exchanges touch, performance, and log data between the device and a host. Enable it in the application's prj.conf:

CONFIG_QUL_DEVICELINK=y

The module then applies the platform port's DeviceLink devicetree overlay and Kconfig fragment, and selects the matching platform metadata. DeviceLink is a compile-time feature, so run west build-qul-libs after changing the option.

Note: DeviceLink is not supported on native_sim platform port.

For more information, see Porting DeviceLink communication.

Kconfig reference

The following options are available when CONFIG_QUL is enabled. Set them in the application's prj.conf or through west build app -t menuconfig.

OptionTypeDefaultDescription
CONFIG_QULboolnEnables the Qt Quick Ultralite module. When disabled, the module is excluded from the build and qmlprojectexporter is not run. Must be set in prj.conf.
CONFIG_QUL_DEFAULT_CONFboolyAppends the platform's qul_module.conf to EXTRA_CONF_FILE before Kconfig runs, which provides the board's required Qt Quick Ultralite settings. Disable it to use your own configuration. Must be set in prj.conf.
CONFIG_QUL_QMLPROJECT_FILEstringemptyThe path to the .qmlproject file that qmlprojectexporter uses to generate the Qt Quick Ultralite application sources.
CONFIG_QUL_BOARD_DEFAULTSstringemptyThe path to the board-specific BoardDefaults_*.qmlprojectconfig file. Resolved from the platform and the color depth when left empty, which requires that a single file matches or that one of the matching files is marked as the default variant. An explicit value takes precedence.
CONFIG_QUL_PLATFORM_METADATAstringemptyThe path to the platform *-metadata.json file. Resolved from the platform and the host when left empty, under the same conditions as CONFIG_QUL_BOARD_DEFAULTS. When CONFIG_QUL_DEVICELINK is enabled, the matching *-metadata-devicelink.json variant is used.
CONFIG_QUL_SELECTORstringemptyA comma-separated list of QML file selectors, passed to qmlprojectexporter as --selector. Omitted when empty.
CONFIG_QUL_BUILD_TYPEchoiceFrom platform metadataThe build type of the Qt Quick Ultralite libraries. Selected with CONFIG_QUL_BUILD_TYPE_PLATFORM_DEFAULT, CONFIG_QUL_BUILD_TYPE_DEBUG, CONFIG_QUL_BUILD_TYPE_RELEASE, CONFIG_QUL_BUILD_TYPE_RELWITHDEBINFO, or CONFIG_QUL_BUILD_TYPE_MINSIZEREL.

CONFIG_QUL_BUILD_TYPE_PLATFORM_DEFAULT takes the build type from the QulBuildType value in the platform's *-metadata.json file. The other values are passed to qmlprojectexporter as --qul-build-type.

CONFIG_QUL_COLOR_DEPTHchoiceAutoThe framebuffer color depth in bits per pixel. Auto derives the depth from the selected BoardDefaults_<N>bpp.qmlprojectconfig file. Selected with CONFIG_QUL_COLOR_DEPTH_AUTO, CONFIG_QUL_COLOR_DEPTH_8, CONFIG_QUL_COLOR_DEPTH_16, CONFIG_QUL_COLOR_DEPTH_24, or CONFIG_QUL_COLOR_DEPTH_32. A depth other than Auto must be available for the target platform.
CONFIG_QUL_CONTROLS_STYLEstringemptyThe Qt Quick Ultralite Controls style, passed to qmlprojectexporter as --controls-style. Omitted when empty.
CONFIG_QUL_INCLUDE_DIRSstringemptyA comma-separated list of include directories, passed to qmlprojectexporter as --include-dirs. Use it to point at the headers of the C++ interfaces declared with InterfaceFiles. Omitted when empty.
CONFIG_QUL_DEBUG_RTTIchoiceNoneThe amount of debug runtime type information included in the application, passed to qmlprojectexporter as --debug-rtti-information. Selected with CONFIG_QUL_DEBUG_RTTI_NONE, CONFIG_QUL_DEBUG_RTTI_ROOTONLY, or CONFIG_QUL_DEBUG_RTTI_ALL.
CONFIG_QUL_ENABLE_PERFORMANCE_LOGGINGboolnCollects runtime performance statistics. See Qt Quick Ultralite performance logging.
CONFIG_QUL_PERFORMANCE_LOGGING_CONSOLEboolnPrints the performance statistics to the console every two seconds. Requires CONFIG_QUL_ENABLE_PERFORMANCE_LOGGING.
CONFIG_QUL_PERFORMANCE_LOGGING_HARDWAREboolyEnables platform-specific CPU usage logging on the platforms that support it. Requires CONFIG_QUL_ENABLE_PERFORMANCE_LOGGING.
CONFIG_QUL_DEVICELINKboolnEnables the DeviceLink protocol, which exchanges touch, performance, and log data with a host. Must be set in prj.conf. See DeviceLink.

Note: The color depth, performance logging, and DeviceLink options affect the Qt Quick Ultralite libraries. Run west build-qul-libs after changing them.

CMake variable reference

Pass these variables to west build after --, for example west build -b <board> app -- -DQUL_ROOT=<path/to/qul>.

VariableDescription
QUL_ROOTThe path to the Qt Quick Ultralite installation, which must contain the host tools such as qmlprojectexporter, the platform sources, and the CMake infrastructure. The target libraries under QUL_ROOT/lib are used when QUL_INSTALL_DIR does not contain a lib subdirectory.
QUL_PLATFORM_BOARDS_DIRThe directory that contains the Qt Quick Ultralite platform board sources. Resolved from this variable, then the QUL_PLATFORM_BOARDS_DIR environment variable, and finally QUL_ROOT/platform/boards. Set it when the platform sources are not part of the Qt Quick Ultralite installation.
QUL_INSTALL_DIRThe directory that contains the prebuilt Qt Quick Ultralite target libraries for the board. When it has a lib subdirectory, those libraries are used instead of the ones under QUL_ROOT/lib. Defaults to <build-dir>/qul_install, which is where west build-qul-libs installs its output.

Environment variable reference

VariableDescription
QUL_ROOTThe path to the Qt Quick Ultralite installation. Used by both west build and west build-qul-libs when the corresponding command-line option is not given.
QUL_PLATFORM_BOARDS_DIRThe directory that contains the Qt Quick Ultralite platform board sources.
BOARDThe Zephyr board target. Used by west build-qul-libs when --board is not given.
ZEPHYR_TOOLCHAIN_VARIANTThe Zephyr toolchain to build the libraries with. When unset, west build-qul-libs uses host for native_sim boards and zephyr for all others.
ZEPHYR_SDK_INSTALL_DIROverrides the auto-detected Zephyr SDK path.
GNUARMEMB_TOOLCHAIN_PATHThe path to the GNU Arm Embedded toolchain. Required when ZEPHYR_TOOLCHAIN_VARIANT is gnuarmemb.

Porting Qt Quick Ultralite to a Zephyr platform

You can port Qt Quick Ultralite to a Zephyr platform by following the Qt Quick Ultralite Platform Porting Guide. In the reference ports, the following parts have been implemented using Zephyr APIs:

Note: If you have installed any of the supported reference platform port(s), the reference Zephyr port source code is in <QT_INSTALL>/QtMCUs/2.12.3/platform/boards/zephyr/native_sim-zephyr or <QT_INSTALL>/QtMCUs/2.12.3/platform/boards/nxp/common/zephyr.

Zephyr Kconfig options

A platform port that is used with the module provides the Zephyr Kconfig options that Qt Quick Ultralite requires on the target in its qul_module.conf file. The module appends that file to EXTRA_CONF_FILE before Kconfig runs, which applies the options to the application build.

For the options that the reference ports require, see Required Kconfig options on the board pages.

Available under certain Qt licenses.
Find out more.