Bare metal vs. RTOS?
Embedded systems are resource constrained with limited processing power, RAM, and flash memory. Having that in mind, one of the main goals of firmware development is memory-optimized code. And what’s a better approach than running your code directly on hardware in a bare-metal application, without any layers in between, such as an OS? You, as a developer, have complete control over the system's resources, including the processor, memory, and peripherals, and can directly access and manipulate them. This is a very common opinion among junior embedded developers, but not just juniors.
Depending on the company and the tasks, you can spend a lot of time working on only bare-metal or RTOS-only projects without seeing both sides of the story. In this blog post, I will explore the differences between the two approaches.
1. What is RTOS?
RTOS is an abbreviation for Real-Time Operating System. In order to understand the Real-Time part, I will explain what an RTOS is in a nutshell.
The main components of every RTOS are tasks and a scheduler. A task implements functionality through a user-defined function, and it is associated with a data structure that holds important information about the task, such as:
Task name and/or ID,
State, usually described as Ready, Running, Blocked, and Suspended,
Task priority,
Stack size, RAM allocated for task’s stack operations,
Pointer to the function that implements the functionality.
The scheduler is a part of RTOS that is responsible for managing the execution of tasks. The scheduler is responsible for determining which task should be executed next based on their state and priority levels. It is designed to provide a deterministic execution of tasks. This means that the tasks are executed in a predictable timely manner.
2. Deterministic behavior
When designing safety-critical applications, it is important to have deterministic behavior, that is, it is important to ensure that actions of the system are executed within the acceptable time delay from the moment of the event occurrence. For example, it’s important to deploy airbags within 15ms of the crash detection. Some other applications require that critical tasks are executed periodically with an exact frequency.
RTOS scheduler is designed to execute tasks based on their priority (how important or critical they are) and their states, ensuring deterministic behavior.
Bare metal applications can also be deterministic, but you must ensure the duration of every task. This makes adding new features in bare-metal applications challenging if we want to keep them deterministic.
3. Scalability
Making bare metal scalable applications requires good planning and proper software architecture. Still, deterministic behavior is hard to implement. What if low priority task is writing data in a flash? How do you ensure that higher-priority task gets a chance to run? RTOS is addressing these issues. It takes care of scheduling tasks with priority in mind. It can also interrupt low-priority tasks and give resources to higher-priority tasks.
It is possible to write complex applications using the bare metal approach. Still, it’s way easier to do it using RTOS, which supplies you with the needed infrastructure for writing connected and complex applications.
4. So, is RTOS always the better option?
RTOS provides you with infrastructure that ensures both deterministic behavior and scalability, but it comes with the cost of additional resources being used. It requires some RAM to keep things running and also a flash to store the instructions. If you are writing a simple application with limited features that needs to run on a very restricted MCU, then the bare metal is a battery approach, but if you are working on a complex connected application, then an RTOS is a better design choice.
It's important to weigh the trade-offs and choose the approach that best fits the requirements of the project.