People often ask us about if it’s possible to use Qt for software development on microcontrollers (MCU), and if Qt can run without an operating system (“bare metal”). Today we will answer these questions and show you some concrete examples.
What is the point of using microcontrollers?
MCUs are small computers on a single integrated circuit. They’re similar to systems on a chip (SoC), albeit less sophisticated. Microcontrollers are used in automatically controlled products and devices, such as car engine control systems, implantable medical devices, wearables, remote controls, office machines, appliances, power tools, toys, and other embedded systems. The main advantage of using MCUs is their small size and comparatively very low cost – especially for large volumes of production.
So, we can already see the main features of MCUs from the definition: small size, low power consumption and, naturally, low price per unit. Thus, we can say that the main point of using MCU is a natural desire to save cost.
Why use Qt on an MCU?
Low computing power applies certain restrictions to the choice of software development tools, especially if we talk about the GUI, e.g. in regards to firmware size, runtime memory usage and how “fancy” the GUI can be.
Today we do not have a universal GUI library for MCUs. Sure, there are some that could solve some part of the task for this or that particular MCU model, but that is not enough. And quite rarely (or actually never) those libraries are created with “cross-platform-ability” in mind.
Although some commercial toolkits are actually pretty good, in most cases they have a closed source code. So you’re buying a “black box” and risk to find yourself vendor-locked.
Now imagine how great it would be if we could use the Qt framework: cross-platform and comprehensive library of classes (including GUI), with excellent documentation and lots of examples, and with a fantastic Open Source community.
Unfortunately, up to this moment, due to the mentioned hardware restrictions, embedded development with Qt (Qt for Device Creation) was officially supported only on devices of Cortex-A level, mostly under Linux and some commercial RTOSes (INTEGRITY, QNX, and VxWorks).
But today, this situation has changed.
So, we got ourselves a research: investigate the possibilities of running Qt on MCU hardware.
Let’s be clear from the beginning on what microcontrollers we’re talking about exactly because some might start to dream about MCUs with a 12 Mhz CPU and 128 bytes of RAM. That would be quite a gap because Qt’s current hardware requirements are:
- 256 MB of RAM;
- 500 MHz CPU (1 GHz preferred);
- OpenGL ES 2.0 support.
And the boards we selected for the research are:
STM32F469 – ARM Cortex-M4, FPU unit single precision
STM32F746 – ARM Cortex-M7, FPU unit single precision, L1 Cache (Data/Instruction)
STM32F769 – ARM Cortex-M7, FPU unit double precision, L1 Cache (Data/Instruction)
As you can see from specifications, their hardware resources are way lower than what Qt “officially” requires.
Regarding OpenGL support, thanks to Qt Quick 2D Renderer it is not a strict requirement, because we can render our graphics using raster paint engine.
We started with porting the following Qt modules:
How do you port Qt to different target platforms? Well, first we need to understand what exactly is required for Qt to function. And in general, there are two main requirements you need to meet:
- POSIX-compatible operating system;
- C++11-compatible compiler.
Let’s start with C++11 requirement. With version 5.7, Qt started to require platforms to support C++11 because we aim to provide a powerful and modern C++ framework. However, if your platform can only support C++98 at best, then you can of course try to do it with Qt 5.6 (or older), but then considering the fact that new configuration system (so-called Qt Lite) was introduced only with Qt 5.8, it will be a tough task for you to “squeeze” Qt into an MCU environment.
Now regarding POSIX – Portable Operating System Interface. That actually answers the question why Qt does not work on “bare metal” out of the box. Inside Qt we are using a lot of POSIX functions (pthreads, mmap,
open and others), so if we want to run Qt on bare metal, we need to create your own implementation of POSIX – basically implement your own operating system. Fortunately, that isn’t the case in our research.
We decided to use an Open Source RTOS and we chose RTEMS for its most notable features:
- POSIX support;
- supports various file systems, including NFS and FAT;
- includes a port of the FreeBSD TCP/IP stack;
- C++11 support;
- Open Source license (modified GPL);
- an active community.
The process of porting Qt to RTEMS consists of the following steps:
- Configure the board – set clock generator (frequency), memory (SDRAM, caches, MMU), initialize peripheral and so on;
- Port RTEMS to STM32F4/F7 (create a BSP);
- Port Qt to RTEMS:
- Add support for it in Qt Core;
- Create a new QPA plugin.
Porting Qt itself can be presented in the following illustration:
We won’t describe the whole process in detail (from configuring the board till the creation of a new QPA) just yet, even though that’s probably the most interesting part of the research. But this article was aiming only to tell you about the research and not to provide a step-by-step manual. If you are interested in conduction a pilot project, please contact us and submit your request.
To demonstrate the results, we created three firmwares for each board with different demo applications.
Qt Widgets demo
Firmware size: 6.6 MB.
RAM required: 3.4 MB.
As we can see, Qt Widgets runs just fine.
Qt Quick / QML demo
Firmware size: 9 MB.
RAM required: 5 MB.
It’s easy to see that Qt QML’s dragging animation is somewhat slow on STM32F4/F746, but the clocks work rather well. Such behavior is an excellent example of lacking JIT compilation because those MCUs don’t support double-precision floating-point. However, STM32F769 does support it, thus the dragging animation looks much nicer on this board.
We decided not to stop on simple demos and for the third firmware, we tried to run something more interesting. For instance – our recent e-bike demo.
Firmware size: 13 MB.
RAM required: 10 MB.
And even this demo works fine too. By the way, thanks to the cross-platform nature of Qt, we didn’t have to change a single line of code to compile it for RTEMS (the original target was running on Linux).
We can conclude that our research was successful. Sure, it is not a ready out-of-the-box solution right now, but we will continue to work on it.
Current tasks include the following:
- porting more Qt modules, and first of all – libraries from Qt for Automation addon;
- further port optimizations and performance improvements, e.g. to make use of the graphics accelerators provided by the boards, which we haven’t utilize yet;
- further tinkering with the Qt configuration system (Qt Lite);
- adding support for development on MCUs into Qt Creator.
So, what does this research mean for you and your projects? The source code of the new QPA and other modifications in Qt code base will be available in Open Source (most probably under GPLv3), and of course in commercial license too, so you’ll be able to try it out yourself.
And we plan to provide consultancy services for preparing a system image and porting Qt to your MCU-based platform. We’ll have more information about that very soon, so stay tuned!
In the meantime, make sure to sign up for the Qt on MCUs webinar where we tell you more about the topic, show you some demos and answer your questions!