On this page

C

Using Zephyr on native_sim

native_sim is Zephyr's host-based simulation board. Applications built for it are compiled into Linux executables that run directly on the host system, without an MCU or instruction set emulation. For details on the board itself, see the Zephyr native_sim board documentation.

The native_sim-zephyr platform port renders to an SDL window and derives touch events from the mouse pointer, which makes it possible to run a Qt Quick Ultralite application without target hardware.

Compatible versions

Qt Quick Ultralite for Zephyr supports Zephyr 4.4.0 on native_sim.

Prerequisites

  • Qt Quick Ultralite 2.12.3
  • Qt Quick Ultralite native_sim platform package
  • Linux (x86_64)
  • GNU Compiler Collection
  • Zephyr RTOS 4.4.0
  • 64-bit SDL2 development libraries

Note: Linux is the only supported host for native_sim.

SDL2 development libraries

native_sim drives its display and reads pointer input through Zephyr's SDL display and input drivers, which makes SDL2 a requirement as of Zephyr 4.4.

Qt Quick Ultralite supports the 64-bit board target native_sim/native/64, so the 64-bit SDL2 development libraries are required. For more details on host dependencies, see the Zephyr native_sim board documentation.

Display configuration

The display device is resolved from the devicetree zephyr,display chosen node. Its resolution is read from the display's runtime capabilities and used to allocate the Qt Quick Ultralite framebuffer. The port exposes a single screen.

Pointer input is delivered through the Zephyr input subsystem in synchronous mode (CONFIG_INPUT_MODE_SYNCHRONOUS). Mouse events in the SDL window are translated into Qt Quick Ultralite touch events.

Setting the screen size

The screen resolution comes from the SDL display controller node in the devicetree, which defaults to 320x240. To change it, add a board devicetree overlay at app/boards/native_sim_native_64.overlay and set the width and height properties of the sdl_dc node:

&sdl_dc {
    width = <800>;
    height = <480>;
};

Zephyr loads this overlay automatically when building for native_sim/native/64.

Pixel format

The native_sim-zephyr platform port renders in 24-bit color depth.

Memory configuration

The Qt Quick Ultralite dynamic allocations, such as the UI tree, image buffers, and font data, are served from the Zephyr kernel heap sized by CONFIG_HEAP_MEM_POOL_SIZE.

The display framebuffer is allocated from Zephyr's common C library heap instead, which keeps it out of the Qt Quick Ultralite memory consumption measurements. The native_sim-zephyr default configuration sizes both that heap (CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE) and the kernel heap to 10240000 bytes, which accommodates a range of screen resolutions.

Building the application

For generic instructions on setting up and building an application, see Setting up a new application, Setting QUL_ROOT, and Building.

Run the following to build the application for native_sim/native/64:

west build -b native_sim/native/64 app

Required Kconfig options

The native_sim-zephyr platform port ships a qul_module.conf file with the Kconfig settings that Qt Quick Ultralite requires. It is applied through EXTRA_CONF_FILE before Kconfig runs.

To provide the configuration from the application instead, set CONFIG_QUL_DEFAULT_CONF=n and add the options from the port's qul_module.conf to the application's prj.conf:

$HOME/Qt/QtMCUs/2.12.3/platform/boards/zephyr/native_sim-zephyr/qul_module.conf

Building the Qt Quick Ultralite libraries

By default, Qt Quick Ultralite uses the prebuilt libraries from the installation, which are built in the Release configuration for native_sim. To build your own libraries, run:

west build-qul-libs --board native_sim/native/64 --build-type Release

For the complete list of command-line options, see Building the Qt Quick Ultralite libraries.

Application thread

On native_sim, closing the display window makes Zephyr call posix_exit() while the Qt Quick Ultralite thread is still running. This may lead to deallocation of statically allocated items before Qul::Application is destroyed, leading to a crash. The following Qt Quick Ultralite thread code ensures Qul::Application does not have any dangling pointers before it is destroyed:

#include "MainScreen.h"

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

#include <memory>
#include <new>

#define QUL_THREAD_STACK_SIZE 16384
#define QUL_THREAD_PRIORITY   5

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

    static unsigned char storage[sizeof(MainScreen)];
    std::unique_ptr<MainScreen, void (*)(MainScreen *)> item(
        new (storage) MainScreen, [](MainScreen *p) { p->~MainScreen(); });
    Qul::Application app;
    app.setRootItem(item.get());
    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 a Zephyr thread at boot. The thread entry point initializes the hardware and the platform before it starts the Qt Quick Ultralite event loop.

The root item is constructed with placement new into static storage, so it is accounted for as static RAM. It is owned by a std::unique_ptr with a deleter that only calls the destructor. The std::unique_ptr is declared before the Qul::Application, so that the application is destroyed before the root item if the thread stack is unwound.

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.

Running the application

The build produces a host executable. Run it through west:

west build -t run

Alternatively, run the executable directly from the build directory:

./build/zephyr/zephyr.exe

The executable opens an SDL window for the application's display and input.

Known issues and limitations

  • The port does not support hardware layers. Any layer argument passed to the platform is ignored.

Available under certain Qt licenses.
Find out more.