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