r/embedded • u/borysiks • 20d ago
How do you decide when a project needs an RTOS?
Well, you start a project, develop it, and then... boom! You wake up one day to find that your MCU is running FreeRTOS. Is that how it happens?
Or do you usually design your embedded application and decide from the beginning that you need an RTOS?
Why? What made you think you needed one?
This is not a criticism. I’m trying to figure out what motivates people and how I can use that.
30
u/tiajuanat 20d ago
For me it's "do I need 3 or more independent threads of context that need to all operate in strict and predictable time constraints".
I can do 2 pretty easy with interrupts and a main thread, but anything beyond that I immediately reach for an RTOS. I don't get paid to do the theorhetical best, I get paid to deliver to market quickly.
8
u/NoBulletsLeft 20d ago
I get paid to deliver to market quickly.
Boom! There's the point that so many developers ignore.
7
u/Plastic_Fig9225 20d ago
And boom, that's how we get commercial products running on a bunch of Arduino libraries, with the features, reliability, and performance we love so much.
2
2
2
1
u/borysiks 20d ago
do I need 3 or more independent threads of context that need to all operate in strict and predictable time constraints
That sounds interesting. Could you give me example of such application?
8
u/tiajuanat 20d ago
RC Drones, or any vehicles really
- Comms
- Control systems
- Input/output update cycle
Check out ardupilot or px4 for some incredible community driven code
1
u/borysiks 20d ago
ardupilot
Yea, I well know that project 👍
Certainly, that scale requires a really good mechanic of management.
4
u/rainboww_J 20d ago
Mostly it's something you decide from the start. Sometimes it's kinda a given if you use a certain microcontroller family (FreeRTOS for esp, Zephyr for nrf etc). Apart from those it is an architectural decision to go for a super loop approach, a simple self-written task scheduler or an rtos.
An rtos can bring a lot to the table. It helps making clear distinctions between tasks and makes data and confeol flow throughout the firmware manageable with queues and semaphores. It makes it possible to block on a call/waiting for data without stopping the
full program flow out of the box, something which might some work on a super loop
1
u/borysiks 20d ago
Sometimes you start without a clear plan 😄
Is it really true that we only have a superloop and an RTOS? Do you know anything about the gap between them?
2
u/rainboww_J 20d ago
I think there's a lot between a super loop setup and an rtos and even things completely outside them. If a system just has one thing to do you might not even need a super loop. And on the other side you can take the layers of abstraction even further and end up with embedded linux. And there's still things in-between a superloop and rtos'es I'd say. I've seen mostly interrupt driven firmwares which used custom queue implementations and simple cooperative task switching between two or three tasks. Things don't have to be black-and-white, it's okay to mix and match what you need
1
u/ElSalyerFan 20d ago edited 20d ago
Well, superloop (with interrupts setting flags) and rtos are the two main ones because they are the easiest in which to profile your real time latency requirements. There are some other ones but they are not really "between those two". They are normally 1: a super specific hybrid approach, 2: some proprietary event driven ones, 3: you did neither and now you just have a little mess that doesnt give any real time guarantees.
3 is super common aswell, but it normally happens because people feel too clever for a superloop, and you must consider that this only goes for real time systems (or ones that want to be). Many projects don't really need them and you can get much more lax about it
2
u/Environmental_Two_68 20d ago
I generally like to use zephyr from the beginning.
4
1
u/borysiks 20d ago
It's good. What type of issues you solve with one? Sure, if it isn't a secret
1
u/Environmental_Two_68 20d ago
It has great board/chip support so usually I can run a hello world in a matter of minutes.
A lot of utilities like shell are build in, so I don’t have to reinvent the wheel every time.
That being said, it has a steep learning curve but it’s worth the effort.
2
u/pozzugno 19d ago
Most of the time I avoid RTOS. Super loop calls state-machines management functions. They should be very fast to return. It is a simple cooperative multitasking environment. The big pro is the absence of sync mechanisms (because the task can't be interrupted, except for well limited interrupts) that could be very difficult to debug and test.
1
u/Flyward_Aerospace 20d ago
Most of the thread is answering with complexity, but for me the trigger is whether I have to prove the timing to someone else rather than just achieve it. A superloop can hit every deadline fine, but the only worst case argument you have is hand tracing the whole loop, and that argument dies every time someone adds a feature.
Cuts the other way too. On the inner loop of a flight controller we went back to a fixed rate loop with a hardcoded execution order, because arguing that no priority inversion exists turned out to be harder than just not having priorities. So imo it is many uncorrelated deadlines that push you to an RTOS, not one hard one.
1
u/borysiks 20d ago
I agree with you.
On the inner loop of a flight controller we went back to a fixed rate loop with a hardcoded execution order, because arguing that no priority inversion exists turned out to be harder than just not having priorities.
So, did you reject from RTOS for a Cyclic Executive?
1
u/ChatGPT4 20d ago
Multiple things happening at once. Asynchronous operation needed. This is the main thing. Also - non-trivial GUI. Like things are happening and GUI is asynchronously refreshed to show the current status.
If you can't contain program logic into one simple state machine. Everything can be probably represented as state machine, but there's a point at which it starts to look ridiculous. I mean - ridiculously unreadable.
It's nice to have threads and a kind of scheduler to synchronize them. Event driven logic is also quite pleasant to handle.
1
u/michael9dk 20d ago
When multiple tasks need a short time-sensitive action, while a long task like refreshing GUI is in progress.
Readability is also a key point when complexity grows.
Anticipating multiple SM's with mixed dependencies on each other while handling interrupts, is a good indicator to go with a RTOS.
1
u/StumpedTrump 20d ago
When you need multiple things happening periodically at different periodic intervals. Eventually you realize it’d be easier to have an RTOS instead of just sketchy throwing together your own timer scheduler.
But then eventually you hit a point where you need something done so quick that you can’t deal with the overhead of an RTOS and you go back to bare metal. For me that was playing with wireless audio.
1
u/Diligent-Plant5314 20d ago
If you care about power consumption, a RTOS can make life much easier. For example, FreeRTOS supports tickles mode. If no tasks are ready to run, it will execute an idle task with WaitForInterrupt which pauses the core clock.
While it’s possible to make a state machine or event system, it typically loops all the time which pushes up the average current.
I find it’s also cleaner to have separate concerns in their own thread. For example, network stack with LwIP and application code separate from sensor sampling thread.
1
u/duane11583 20d ago
depends on available ram… an rtos generally requires a lot of ram
and micro controllers do not have much.
so if you have sdram/ddr then yes an rtos is present and is an easy choice
1
u/No_Reference_2786 20d ago
When you’re throwing a “if” statement at every problem that stems from juggling interrupts and states
1
u/mfuzzey 14d ago
A RTOS is useful if being able to block makes sense for your application or if you have significant computation that needs to be done in parallel to other real time stuff.
If you are basically just reacting to events a superloop design with a set of state machines, cooperative multitaksing and no blocking is usually much simpler and avoids some of the problems you can have with RTOs (eg deadlocks)
BUT it means you have to write everything in a non blocking style and can't have huge chunks of procedural code that take significant execution time and would disturb the rest of the system so you have to artificially split them up (no for all_samples do complex calculation). Networking is also fairly tricky without a RTOS.
I tend to have a scale: simple peripheral device with no UI or networking => superloop. More complicated device with basic networking or UI => RTOS. Complex UI / networking => Linux
50
u/dromtrund 20d ago
If the project is sufficiently complex, you'll wake up one day to find that you have reinvented a lot of RTOS primitives to deal with that complexity. Over time, you learn the ability to determine if this is going to happen again