Developing Embedded Linux Applications with Qt

Introduction


  • Andy Nichols
  • Digia
  • Qt Developer
  • freenode irc: nezticle
  • twitter: @nezticle


Outline


  • Hardware
  • Device Software
  • Sysroots
  • Toolchains
  • Buildroot
  • Qt Creator
  • Tips and Tricks
 

Hardware

The CPU












ARM


ARM9 ARM10
ARM11
ARMv7


ARMv5
ARMv6
Cortex-A

System on a Chip (SoC)


The GPU

Imagination Technologies PowerVR


  • Beagleboard
  • Apple Devices



Broadcom VideoCore



Vivante




  • iMX6 
  • Google Chromecast

Wireless







Device Software

Bootloader


  • Das U-Boot
  • multiple stages

Linux Kernel


  • defconfig 
    • (eg arch/arm/configs/bcmrpi_defconfig)
  • Kconfig 
    • make menuconfig
    • make xconfig
  • zImage vs uImage
  • firmware
  • modules


Userland Filesystem


  • applications
  • libraries
  • utilities and tools

Sysroot

What's in a Sysroot?


  • Development files
  • Include headers
  • *.so files
  • Debug symbols

Toolchain


  • compilers
  • host tools

Getting the parts necessary for Embedded Linux Development

Yocto Project


  • OpenEmbedded
  • BitBake
  • Poky
  • meta-layers


Qt Enterprise Embedded


  • aka Boot to Qt
  • Digia Embedded offering
  • All tools necessary to get started
    • device images
    • sysroot
    • toolchain







Buildroot Demonstration

Obtaining a Toolchain


  • CodeSourcery
  • Linaro
  • Crosstool-NG

Contents of the Filesystem


  • Dependencies of Qt 5 modules
  • Dependencies of your application
  • Dependencies of your hardware
  • Busybox

Configuration of Linux Kernel


  • Version
  • defconfig
  • Kconfig

Now just run "make" to build an Image, Sysroot, and Toolchain

Building Qt 5 yourself

Understanding the mkspec's relationship with Configure



  • -platform
  • -xplatform
  • -device

Raspberry Pi qmake.conf


 # qmake configuration for Broadcom's Raspberry PI
# http://wiki.qt-project.org/Devices/RaspberryPi

include(../common/linux_device_pre.conf)

QT_QPA_DEFAULT_PLATFORM = wayland

QMAKE_LFLAGS           += -Wl,-rpath-link,$$[QT_SYSROOT]/opt/vc/lib

QMAKE_LIBDIR_OPENGL_ES2 = $$[QT_SYSROOT]/opt/vc/lib
QMAKE_LIBDIR_EGL        = $$QMAKE_LIBDIR_OPENGL_ES2

QMAKE_INCDIR_EGL        = $$[QT_SYSROOT]/opt/vc/include \
                          $$[QT_SYSROOT]/opt/vc/include/interface/vcos/pthreads \
                          $$[QT_SYSROOT]/opt/vc/include/interface/vmcs_host/linux
QMAKE_INCDIR_OPENGL_ES2 = $${QMAKE_INCDIR_EGL}

QMAKE_LIBS_EGL          = -lEGL -lGLESv2

contains(DISTRO, squeeze) {
    #Debian Squeeze: Legacy everything
    QMAKE_LIBS_OPENGL_ES2   = -lGLESv2 -lEGL
    QT_QPA_DEFAULT_PLATFORM = eglfs
} else:contains(DISTRO, arch) {
    #On principle: no wizardry required
} else {
    #This is not strictly necessary
    DISTRO_OPTS += deb-multi-arch
    DISTRO_OPTS += hard-float
}

QMAKE_CFLAGS           += \
                          -marm \
                          -mfpu=vfp \
                          -mtune=arm1176jzf-s \
                          -march=armv6zk \
                          -mabi=aapcs-linux

QMAKE_CXXFLAGS          = $$QMAKE_CFLAGS

EGLFS_PLATFORM_HOOKS_SOURCES = $$PWD/qeglfshooks_pi.cpp
EGLFS_PLATFORM_HOOKS_LIBS = -lbcm_host

include(../common/linux_arm_device_post.conf)

load(qt_config)

Raspberry Pi qeglfshooks.cpp


 class QEglFSPiHooks : public QEglFSHooks
{
public:
    virtual void platformInit();
    virtual void platformDestroy();
    virtual EGLNativeDisplayType platformDisplay() const;
    virtual QSize screenSize() const;
    virtual EGLNativeWindowType createNativeWindow(const QSize &size, const QSurfaceFormat &format);
    virtual void destroyNativeWindow(EGLNativeWindowType window);
    virtual bool hasCapability(QPlatformIntegration::Capability cap) const;

    QEglFSCursor *createCursor(QEglFSScreen *screen) const {
        return new QEglFSPiCursor(screen);
    }
};

void QEglFSPiHooks::platformInit()
{
    bcm_host_init();
}

EGLNativeDisplayType QEglFSPiHooks::platformDisplay() const
{
    dispman_display = vc_dispmanx_display_open(0/* LCD */);
    return EGL_DEFAULT_DISPLAY;
}

void QEglFSPiHooks::platformDestroy()
{
    vc_dispmanx_display_close(dispman_display);
}

QSize QEglFSPiHooks::screenSize() const
{
    uint32_t width, height;
    graphics_get_display_size(0 /* LCD */, &width, &height);
    return QSize(width, height);
}

EGLNativeWindowType QEglFSPiHooks::createNativeWindow(const QSize &size, const QSurfaceFormat &format)
{
    return createDispmanxLayer(QPoint(0, 0), size, 1, format.hasAlpha() ? DISPMANX_FLAGS_ALPHA_FROM_SOURCE : DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS);
}

void QEglFSPiHooks::destroyNativeWindow(EGLNativeWindowType window)
{
    destroyDispmanxLayer(window);
}

bool QEglFSPiHooks::hasCapability(QPlatformIntegration::Capability cap) const
{
    switch (cap) {
        case QPlatformIntegration::ThreadedPixmaps:
        case QPlatformIntegration::OpenGL:
        case QPlatformIntegration::ThreadedOpenGL:
        case QPlatformIntegration::BufferQueueingOpenGL:
            return true;
        default:
            return false;
    }
}

QEglFSPiHooks eglFSPiHooks;
QEglFSHooks *platformHooks = &eglFSPiHooks;

Qt 5 configure options



export HOST_DIR=$BUILDROOT_DIR/host
export STAGING_DIR=$BUILDROOT_DIR/staging
export TARGET_DIR=$BUILDROOT_DIR/target

./configure -prefix /usr -hostprefix $HOST_DIR/usr -release -device pi -device-option CROSS_COMPILE=$HOST_DIR/usr/bin/arm-raspberrypi-linux-gnueabi- -sysroot $STAGING_DIR -no-neon

Building, Installation, Deployment



  • make
  • make install
  • qmake
  • copy files to device image
    • libraries
    • binaries

Demonstration: Setting up Qt Creator

Tips and Tricks

EGLFS







Single top level EGL window surface

EGLFS Environment Variables


  • QT_QPA_EGLFS_HIDECURSOR
  • QT_QPA_EGLFS_SWAPINTERVAL
  • QT_QPA_EGLFS_PHSICAL_{WIDTH/HEIGHT}
  • QT_QPA_EGLFS_{WIDTH/HEIGHT/DEPTH}
  • QT_QPA_EGLFS_CURSOR

QtWayland



  • Multiple window surfaes
  • Window compositors

Modules to Avoid



  • QtQuick1
  • QtScript
  • QtWidgets
  • QtOpenGL

Questions?

Contact Info



  • Andy Nichols
  • andy.nichols@digia.com
  • freenode IRC: nezticle
  • twitter: @nezticle

Developing Embedded Linux Applications with Qt

By nezticle

Developing Embedded Linux Applications with Qt

  • 1,464