Article
RTOS vs. Bare-Metal Firmware: How to Choose for Your Next Product
Every embedded product starts with the same question buried inside a bigger one: should the firmware run bare-metal, on top of a real-time operating system (RTOS), or eventually move to embedded Linux? Get it wrong early and you either over-engineer a simple product or spend months fighting timing bugs an RTOS would have prevented.
What “bare-metal” actually means
Bare-metal firmware runs directly on the microcontroller with no scheduler underneath it — typically a single main loop, or a main loop plus interrupt service routines. There’s no task abstraction, no built-in priority system, and no context switching. You write the control flow yourself, from reset vector to shutdown.
What an RTOS adds
An RTOS like FreeRTOS or Zephyr adds preemptive multitasking: multiple independent tasks, each with a priority, that the scheduler interleaves based on timing and priority rather than the order you happened to write them in. It also typically brings queues, semaphores, and mutexes for safely passing data and coordinating between tasks, plus (in Zephyr’s case) built-in networking and device driver frameworks.
When bare-metal is still the right call
If a product has one or two things to do, on a predictable cycle, with generous timing margins — a simple sensor node that wakes up, takes a reading, and sleeps again, for example — bare-metal is often genuinely simpler to build, debug, and certify. Every added abstraction is something that can go wrong, and an RTOS is not free: it costs flash, RAM, and a real learning curve if your team hasn’t used one before.
When to move to an RTOS
The signal is usually the main loop itself: if it has grown into a tangle of flags and state machines trying to interleave a control loop, a communications stack, and background housekeeping, an RTOS’s task model is doing the same job the language already has abstractions for. It’s also the right call whenever timing correctness genuinely matters — a control loop that must run on a fixed period regardless of what else the device is doing — since a scheduler with real priorities handles that far more predictably than a hand-rolled main loop.
Our take
We don’t default to an RTOS because it’s more “proper” engineering, and we don’t stay bare-metal out of habit either. The call comes down to how many independent things the firmware genuinely has to juggle, and how strict the real-time guarantees need to be. We’ve migrated products in both directions — adding an RTOS to a bare-metal codebase that outgrew its main loop, and occasionally simplifying back down when a product’s scope shrank. See our RTOS development page for how we approach FreeRTOS and Zephyr projects specifically.
FAQ
What is the difference between bare-metal firmware and an RTOS?
Bare-metal firmware runs with no scheduler — usually a single main loop plus interrupts, with all timing and sequencing handled by hand. An RTOS adds a scheduler that runs multiple prioritized tasks, switching between them based on timing and priority, plus tools like queues and semaphores for coordinating between them.
Can I migrate a bare-metal product to an RTOS later without a full rewrite?
Usually yes. The application logic itself often carries over more than teams expect — the bigger work is restructuring the main loop into discrete tasks and replacing ad-hoc flags with proper RTOS primitives (queues, semaphores) for communication between them.
Does adding an RTOS slow down a real-time system?
Not meaningfully if it’s architected correctly. Context switching and scheduling overhead are typically microseconds on modern microcontrollers — far smaller than the timing problems an RTOS’s priority system prevents in a sufficiently complex application.
Is FreeRTOS good enough, or do we need something like Zephyr?
FreeRTOS is a strong choice for straightforward real-time applications where you mainly need reliable task scheduling. Zephyr is worth considering when you also need built-in networking stacks, a device driver framework, or you expect the product to grow more connected features over time.
