The best part about real-time OS (RTOS) availability in 2024 is that we developers are positively spoiled for choice, but as a corollary this also makes it a complete pain to determine what the optimal choice for a project is. Beyond simply opting for a safe choice like FreeRTOS for an MCU project and figuring out any implications later during the development process, it can pay off massively to invest some time up-front matching the project requirements with the features offered by these various RTOSes. A few years ago I wrote a primer on the various levels of ‘real-time’ and whether you may even just want to forego an RTOS at all and use a simple Big Loop™ & interrupt-based design.
With such design parameters in mind, we can then look more clearly at the available RTOS options available today, which is the focus of this article. Obviously it won’t be an exhaustive comparison, and especially projects like FreeRTOS have seen themselves customized to various degrees by manufacturers like ST Microelectronics and Espressif, among others. This also brings to the forefront less pleasant considerations, such as expected support levels, as illustrated by e.g. Microsoft’s Azure RTOS (formerly ThreadX) recently getting moved to the Eclipse Foundation as the Apache ThreadX open source project. On one hand this could make it a solid open-source licensed RTOS, or it could have been open sourced because Microsoft has moved on to something else and cleared out its cupboard.
Thus without further ado, let’s have a look at RTOSes in 2024 and which ones are worth considering, in my opinion.
Answering Some Questions
A crucial distinction when looking at operating systems for embedded systems is the kind of platform it is. If it’s something along the lines of an x86, Cortex-A ARM or similar, you’re likely looking at a desktop-like system, where a real-time OS such as VxWorks, QNX, a BSD or Linux (with or without real-time patches) is probably the best choice, if only due to hardware support concerns. For situations where hard real-time considerations are the most essential, an FPGA/CPLD-based solution might instead be worth it, but this is of course less flexible than an MCU-based solution.
If at this point an MCU-based solution seems the most sensible one, the next logical question is ‘which one RTOS?’. The answer to this is hidden somewhere in long lists of RTOSes, such as the one found over at Wikipedia, or the one over at the OSRTOS website. Assuming for a moment that we are looking only at open source RTOSes here that are seeing active development, we can narrow it down somewhat to the following list:
Of note is that the popular Mbed project was abandoned in July of 2024, rendering the future of this RTOS highly uncertain. Even with that one taken out of the picture, we are still left with an impressive list. Is NuttX better than ThreadX? What about Zephyr versus RIOT or ChibiOS/RT? Merely reading the bullet points for the features gets one only so far. Perhaps the most important questions here pertain to issues such as:
- Build system requirements
- Demands on a specific compiler (version)
- Programming languages one can use with the OS
- Whether direct hardware access to peripherals is allowed or require going through a HAL of some description.
- Support availability when something inevitably doesn’t work as expected.
- Accessibility of the source code when reading through it (readability, documentation, etc.)
Baseline Expectations
The baseline for the build environment demands and supported features is set here at FreeRTOS. It runs on a wide range of (MCU) platforms, provides a number of schedulers, SMP support, happily compiles with just about any compiler toolchain and is C-based so can be used with any programming language that can cooperate with C APIs. Direct hardware access is the standard way for peripherals and the OS generally gets out of your way beyond scheduling and multi-tasking matters. This ‘stay out of the way’ approach persists with developer tools and configuration, which works as easily in Vim as in any other editor.
ThreadX
As of writing the documentation is a stack of Markdown files on GitHub which are clearly not converted yet from their Azure OS era, and ‘getting started’ refers to connecting to the Microsoft Azure cloud. Building the library is apparently done using CMake, Ninja and the standard ARM GCC toolchain for ARM targets, but where’s a sample project and what about other MCU platforms?
After confusing myself clicking through the ‘documentation’ for a while, I’m sure that I would not pick this RTOS as I am spending far too much time even figuring out the basics.
Contiki-NG
Documentation exists and doesn’t look too bad, but you’re pushed right into using a Docker image for development. Fortunately native installation instructions are provided for Linux and MacOS, but not Windows. It’s clear that this RTOS is focused on Internet of Things projects, while the ability to easily run the code as a native (Linux) process is nifty.
Feels like this RTOS could be nice for network-related projects.
OpenERIKA
Confusing website and the impression is that it’s ‘free’, but do not expect any support unless you’re willing to pay for it. Hard pass.
MicroC/OS
I’m sure that Silicon Labs had good intentions with their Micrium OS site, but it’s too hard to find anything on it, never mind how to get started with the thing, plus it seems locked to Silabs devices. Ditto for the Weston-Embedded website. Hard pass.
RIOT
Seems to use basic tools and the standard platform toolchains per the ‘getting started‘ documentation. Build system is GNU Make-based, which is very flexible and should integrate with other build systems with little issue. Quite a lot of documentation to dig through, and might be worth scratching an itch with that FreeRTOS doesn’t cover?
NuttX, Zephyr, ChibiOS/RT
RTOSes which have lots of bullet points are kinda fancy, but demanding the use of KConfig with NuttX, the insistence on setting up a special Python-based development with Zephyr and the seemingly hard requirement to use the special IDE with ChibiOS/RT all makes for problematic choices that will make developing with these either impossible — KConfig on Windows — or integrating with other build systems impossible to tedious.
While I’m not a Python hater, my experiences with Python-based build environments and tools are very negative, and I’d rather avoid such unnecessary dependencies in a development workflow. If you’re a Python fan, you might want to look more seriously at Zephyr.
With that said, the remaining RTOSes in the list are fairly small and can probably be skipped safely.
FreeRTOS
Back in my original 2021 article I covered getting started with FreeRTOS, which at the time was focused mostly on STM32 and similar ARM-based MCUs. Since then I have extensively expanded my use of FreeRTOS in the form of Espressif ESP32 development, both on the base ESP32 MCU and the ESP32-S3. This provided a range of interesting perspectives, also since I was porting significant amounts of cross-platform C and C++ code to these MCUs.
An important aspect of FreeRTOS is that it is commonly included in MCU SDKs, as is the case with Espressif’s ESP-IDF. It supports three different versions of FreeRTOS: the single-core ‘vanilla’ FreeRTOS, the Espressif (SMP) version and Amazon’s SMP FreeRTOS. Espressif’s version is optimized for the dual-core design of the ESP32 and ESP32-S3 and the default choice. What this demonstrates clearly is that the strength of FreeRTOS lies in its flexibility. You can slot in any custom scheduler, heap allocation algorithm, and pile on additions that are optimized for the target platform.
ESP-IDF provides partial POSIX compatibility, which uses FreeRTOS primitives internally. In order to port projects based on the cross-platform PoCo libraries, I added FreeRTOS support to these in the compatible NPoCo project. With this approach I can use virtually all of the features provided by the PoCo libraries also with (ESP-IDF) FreeRTOS, while allowing for the exact same code to compile on desktop platforms. The only platform-specific elements (e.g. start-up and peripheral use) are handled by compile-time preprocessor inclusions.
Drawing Conclusions
Although there are many ways to go about developing a project and advocating a particular approach is the best way to end up forever shunned by friends & colleagues, looking at a different approach can be enlightening. Over my own career I have gravitated strongly towards simplicity and reducing potential pain points. A big part of this is finding the optimal ways to do as little work as possible, which is where my own approach to MCU-based RTOSes comes from. I really don’t want to write more code than absolutely necessary, also because new code has new bugs.
As software is incredibly flexible, the real value in an (RT)OS lies in the scheduler, heap allocator and similar elements which provide the primitives on which other features can be built. While many RTOSes seem to go out of their way to (incompatibly) replicate the scope of the entire Linux kernel space & userspace in miniature, this to me at least seems restrictive. What I personally appreciate in FreeRTOS is that you can have as much or as little FreeRTOS in your code as you want, making it extremely hackable.
For others their priorities may be completely different, in which case any of the other RTOSes may work better, which is also perfectly fine. As long as the project is completed on time, within budget and no keyboards were thrown through the room, there are no wrong choices.