It’s always nice to have a choice, but when it comes to real-time operating systems (RTOS), there are just too many! If you’ve ever taken the time to search the web, you’d find that there are over a hundred different RTOS’s out there! Some are general, some try to differentiate by industry such as the IoT. Others claim they are better because they are commercial products while open source ones claim they are free and just as good as the commercial ones. Ask any three engineers about their RTOS choice, and you’ll likely find they all have a different favorite.
I’ve always been a big fan of Lord of the Rings, with a single ring to rule them all. Wouldn’t it be nice if there was just a single RTOS? The answer is actually NO! The embedded systems space is just too diverse to create one RTOS that would meet the needs of everyone. People working in safety critical software would want robust, laser tight determinism where commercial developers would be happy with hitting soft real-time needs and view the robust determinism as overkill. There will never be a single RTOS to rule them all but what if the RTOS itself is more like the rings of power and an operating system abstraction layer (OSAL) is the one ring?
Ruling the RTOS through OSALs
OSALs are an incredibly useful tool that developers can leverage to abstract out the specific RTOS that they have chosen. An OSAL is essentially a generic interface that can be used to interact with and control any number of existing RTOS’s. If one developer likes FreeRTOS, they simply wrap the FreeRTOS API’s with the OSAL. If another developer wants to use ThreadX, or uC OS III, or some other RTOS, they simply wrap the RTOS calls with the OSAL interface.
There are actually quite a few advantages to using an OSAL. First, the OSAL allows developers to decouple their application code from the RTOS. With so many options out there, and many coming in and out of style, teams shouldn’t be writing their applications around an RTOS. The RTOS is just a component or tool and the less dependency there is on the RTOS in the application the better! A perfect example might be where one RTOS is used during proof-of-concept because it is free while a safety certified version may be used during development and production. With an OSAL in place, there is no need to rewrite application code, just redirect the OSAL interface to the other RTOS and recompile.
Second, the OSAL allows a developer to architect their software without caring about what RTOS is used. A software architect wants to work with details that are abstract so that they can focus on the architecture and the application business rules. The nitty gritty RTOS details therefore get pushed behind the OSAL and become an implementation detail that the application architects don’t need to think about. (Yes, this does limit the use of RTOS specific features but for scalable and flexible architecture design we push these details to the implementers).
Finally, with the RTOS behind the OSAL, it makes it much easier for the software to be tested and simulated. When an RTOS is tightly coupled to the application, developers need to figure out how to get the RTOS to run on a continuous integration server and how to get it to behave properly in simulation and integration testing. With the OSAL, the behavior can be much more easily mocked which can help save time but more importantly prevent developer stress levels from reaching critical.
There will never be just a single RTOS that everyone in the embedded systems industry uses. The best that we can hope for is for developers with the embedded systems industry to adopt a single OSAL that acts as a standard interface for any embedded application. There are potential OSALs out there such as CMSIS-RTOS v2 for Arm users and a few other microcontroller vendor specific ones out there. I don’t yet feel though that development teams are adopting them the way that they should.
An OSAL is advantageous because it allows developers to write their applications without needing to immediately select the RTOS they will use. They can simulate the behavior of a generic RTOS and write their application code, even testing it while delaying the specific RTOS they will use until the implementation phase of their project. The OSAL is the closest we will come to having one RTOS to rule them all.
If you’ve used ST’s CubeMX configuration tool and added FreeRTOS to your project, it actually uses an OSAL, specifically CMSIS-OS or CMSIS-RTOS as mentioned above. It’s a nice configuration tool although I’m not sure how easy it would be to swap out FreeRTOS for another RTOS underneath. But it should be do-able if you have the right wrapper code.
There are some disadvantages to that approach to consider though .
The ones that come to mind immediately:
– Performance: any adaptation layer will have a performance impact
– Functionality: the OSAL will by nature be a subset all all the supported RTOS common functionalities
– Clarity. This one is somehow a consequence of the previous one. the OSAL will typically target to cover all the common ones…. at least the one that are close enough. In my experience, with that approach, when truly questioning services/API , one often find it difficult to get a clear answer, and oftentimes discover what the API does varies slighting depending on the OS behind the OSAL
To conclude, there is an alternative to OSAL: select an RTOS that follow a standardized API (such as ARINC653)
Thanks for the comments. I agree with your points although I’ll also point out that with today’s hardware and compilers, the performance hit is minimal to non-existent. I do find there are few RTOS’s that adhere to a standardized API. I really wish they would! (Also 100% with you on functionality and clarity. Unfortunately this is sometimes the price that’s paid for flexibility and scalability). Thanks again!
I don’t use an RTOS. It just seems unnecessary. I’ve seen more botched code using an RTOS when it was not needed. Modern ARM MCU’s have vectored interrupts with priority settings. If you know what you’re doing, the time critical code can be placed into a high priority ISR, and background tasks can run in main(). Toggle GPIO pins at critical points and monitor them with an oscilloscope. Keep all variables global (gasp!) and debugging is easy.
However, if speed and determinism is not as important (as is the case with most embedded projects) I use microPython (although it is possible to get some level of derterminism with microPython). This saves me hours of programming time.
Besides, if I do need a real OS, say for networking or GUIs, I’ll use a Linux based embedded system. They’re getting really cheap. Check out the Onion Omega2 for about $10. (https://onion.io/omega2/ or sparkfun.com)
Thanks for the comments. I mostly agree although more and more I personally forego the baremetal approach and go straight to the RTOS. I do see quite a few botched RTOS implementations but I think that is more an issue with education and experience than the RTOS itself. Thank-you for sharing your experiences!