All jobs / Embedded / hardware
RTOS interview questions
RTOS questions a Embedded / hardware can be asked, from first job to senior. Open one to see the strongest answer and why it works.
When do you reach for a mutex, and when for a binary semaphore?
The strongest answer: A mutex protects shared data — it has an owner who must give it back, and it can lend priority to whoever is blocked; a binary semaphore signals an event from an ISR or a task to a task
Why it works: Exactly — ownership and priority inheritance are what make a mutex the right tool for shared data.
- Mutex guards data; semaphore signals events.
- A mutex has an owner; give it back.
- Only a mutex can inherit priority.
- Signal from an ISR with a semaphore.
When do you pick an RTOS over a main-loop, and when not?
The strongest answer: RTOS when I have concurrent deadlines I cannot honestly interleave — main-loop when the work is a simple sequence I can bound
Why it works: Exactly. Concurrency you can name. Fashion and logos are not deadlines.
- RTOS for named concurrent deadlines.
- Main-loop when the sequence is boundable.
- Not a fashion pick.
- Not a logo pick.
A UART interrupt needs to hand a byte to a task through an RTOS queue. What must the ISR do differently?
The strongest answer: Call the FromISR version of the queue API, which never blocks, and pass the higher-priority-task-woken flag to the yield macro so the woken task runs as the ISR exits
Why it works: Right — no blocking, and the yield is what makes the handoff prompt instead of waiting for the next tick.
- ISRs use the FromISR calls and never block.
- Send with the FromISR variant.
- Pass the woken flag to the yield.
- Keep the interrupt priority RTOS-callable.
Average loop time is fine; the plant oscillates. What did you miss?
The strongest answer: Jitter and worst case — I budget max, not mean, and I look at interrupts that steal the edge
Why it works: Exactly. Control cares about the late one. Averages hide the thief.
- Budget worst-case, not mean.
- Find IRQs that steal the edge.
- Do not hide jitter in an average.
- Do not blame the plant first.
A task should sample every 10 ms. It sleeps for 10 ms at the end of each pass, and over minutes the period slips.
What is wrong?
The strongest answer: A plain delay counts from the moment you call it, so the work time is added to every period; the delay-until form sleeps to an absolute next-wake time and holds the period
Why it works: Right — delay-until anchors to the previous wake time, so jitter stops accumulating into drift.
- Anchor a period to absolute time.
- A plain delay measures from now.
- Delay-until holds a fixed period.
- Drift ruins filters and timestamps.
Two tasks write a global “state” byte. What is the grown-up move?
The strongest answer: A queue or a critical section I can name — I do not add a delay to “let the other one finish”
Why it works: Exactly. A real exclusion. Volatile is visibility, not a lock. Sleeps and prints are folklore.
- Queue or named critical section.
- No luck delays.
- volatile ≠ exclusion.
- Printf ≠ a lock.
A low-priority task holds a lock a high-priority task needs. What do you name?
The strongest answer: Priority inversion — I want inheritance or a ceiling, or I redesign the lock, I do not raise everything to max
Why it works: Exactly. Name it, then inheritance/ceiling/redesign. Max-priority-everything is a busy-loop OS.
- Name inversion.
- Inheritance, ceiling, or redesign.
- Do not flatten every priority.
- Do not sleep-turn-take.
One task corrupts another’s stack. What do you add besides “be careful”?
The strongest answer: MPU regions or separate privilege, plus a watermark — careful is not a boundary
Why it works: Exactly. Hardware boundaries. Merging and enlarging hide the thief.
- MPU or privilege split.
- Keep watermarks.
- Careful ≠ a boundary.
- Do not merge smashers.
You have a 2 ms control deadline. What number do you present?
The strongest answer: Worst-case with the IRQs you allow, not a mean from a happy bench — and what you disable to hold it
Why it works: Exactly. Deadline is a max. Host cycle counts are a different CPU.
- Present worst-case, allowed IRQs.
- Say what you disable to hold it.
- Means are not the deadline.
- Host cycle counts are not the chip.
A low-priority logger never runs. What do you check before “buy a faster MCU”?
The strongest answer: Whether high tasks never block — starvation — I add a bound or a budget, I do not raise the logger to max
Why it works: Exactly. Starvation is a priority story. VIP loggers and ISR logs steal the plant.
- Check starvation before a faster MCU.
- Bound the high tasks.
- Do not VIP the logger.
- Do not log from an ISR.
Two teams share one firmware, each has added mutexes, and you have now had two hangs that reproduce about once a week.
What policy do you put in place?
The strongest answer: One documented lock order everybody takes locks in, short critical sections, no blocking call while holding a lock, and a review rule that any new lock joins the order
Why it works: Exactly — circular wait is the condition you can design away, and a written order plus a review rule is how it stays away.
- Remove circular wait by design.
- Write one global lock order.
- No blocking calls while holding a lock.
- Every new lock joins the order.
What does a staff engineer pin on the wall for a control product?
The strongest answer: A worst-case budget with owners for each steal — I do not keep it in one person’s head
Why it works: Exactly. Owned steals. Slogans and invented percentiles are décor.
- Worst-case budget, named owners.
- Not a demo mean.
- Not a slogan.
- No invented deadline percentile.