Embedded Firmware Interview Questions and Answers

Embedded firmware interviews rarely ask you to reverse a linked list. They ask what happens between a pin changing and your handler running, why a loop that waits on a flag hangs only in the release build, and how you would find out why a sensor reads 0xFF. This page collects the questions that come up most in embedded systems and embedded C interviews, gives a short answer to each, and links an exercise where you write the code and run it on a simulated STM32F4.

How to use this page

Read a question, say your answer out loud, then compare. Where a question links an exercise, do the exercise: an interviewer can tell the difference between someone who has read about EXTI and someone who has wired it up. Every exercise runs in the browser, compiles your C for an ARM Cortex-M4, and grades it on a simulated board, so there is nothing to install and no board to buy.

Embedded C

What does volatile tell the compiler, and when do you need it? It says the value can change outside the code the compiler can see, so every read and write in the source must happen in the program, in order. You need it on memory-mapped registers and on any variable an interrupt handler writes and the main loop reads. It does not make an access atomic, and it is not a lock.

What is a read-modify-write, and how can it go wrong? Setting one bit in a register means reading the register, changing the bit, and writing the whole value back. If an interrupt changes the same register between your read and your write, its change is lost. Set and reset registers such as BSRR exist so a single write can change one pin without touching the others.

How do you reach a peripheral's registers from C? Through a pointer to its fixed address, usually a struct laid over the register block so each field lands on its register. Practise it with Nameplate, which reads a chip register through a pointer, and Floor Plan, which drives two GPIO ports through one struct.

Why does struct layout matter when the struct describes hardware or a wire format? The compiler may insert padding to align fields, so a struct that looks like the datasheet's byte layout may not be. Fixed-width types, explicit offsets and a size check at compile time catch it before the hardware does.

GPIO, timers and interrupts

Walk through what happens from a pin edge to your interrupt handler. On an STM32F4 the pin is routed to an EXTI line through SYSCFG, the line is unmasked and given an edge, and the matching interrupt is enabled in the NVIC. When the edge arrives, EXTI sets a pending bit, the NVIC enters the handler, and the handler clears the pending bit by writing a 1 to it. Build it yourself in Doorbell.

How do you debounce a button? A mechanical contact bounces for a few milliseconds. Sample it on a fixed tick and report a change only after the level has held for a set time, rather than reacting to every edge. Write one in Steady.

How do you make a timer interrupt fire every millisecond? Divide the timer's input clock with the prescaler, set the auto-reload value so the counter wraps once per period, enable the update interrupt, and count in the handler. The arithmetic is the question: know which bus clock feeds the timer. SysTick does the same job with a single reload value. Practise with Timekeeper, Stopwatch, Vigil and Conductor, and the SysTick version in The Fly.

What belongs in an interrupt handler, and what does not? Clear the cause, capture what you need, hand it off, and return. Long work, blocking calls and printing belong in the main loop or a task. Data shared with the main loop needs a single writer, volatile access, and a buffer that cannot be read while half written.

Serial buses

Polling, interrupts or DMA for a UART? Polling is fine for a boot banner. Interrupts suit command and response traffic. DMA suits streams, because the hardware moves the bytes and the CPU only hears about whole buffers. The guide Interrupts vs. DMA on the Cortex-M4 goes deeper. Write an echo in Parrot and a DMA transmit in Conveyor.

How is a UART baud rate set? The baud rate register divides the peripheral clock, so the divisor depends on which clock feeds that USART. Compute it at run time in Tuning Fork.

SPI or I2C, and what does each cost? SPI is fast and full duplex, with one chip select per device and no acknowledgement. I2C needs two wires for many devices and addresses each one, at the cost of speed and an open-drain bus that can be held by a misbehaving device. Practise SPI in Roll Call, Flight Recorder and Postcard, and I2C in Thermometer, Census, Scroll and Server Room Monitor.

RTOS

What is priority inversion? A high-priority task waits on a lock held by a low-priority task, and a medium-priority task that needs neither runs instead, so the high-priority task waits on work it does not depend on. Priority inheritance on the mutex is the standard fix.

How do you hand an event from an interrupt to a task? Use the FromISR variant of a queue, semaphore or task notification, and request a context switch on the way out if a higher-priority task woke. Build it in Turnstile.

What is starvation, and how is it different from deadlock? A starved task is ready but never scheduled, because a higher-priority task never blocks and so always runs ahead of it. In a deadlock, tasks wait on each other and none can run.

How do you size a task stack, and how do you catch an overflow? Start from the deepest call chain plus interrupt frames, fill the stack with a pattern and measure the high-water mark under load, and turn on the RTOS overflow check.

Debugging questions

Many loops include a debugging round: here is a symptom, find the cause. There is no list to memorise for that; what is graded is how you narrow it down. Read the registers before you change the code, change one thing at a time, and say what each observation rules out. The debug drills in STM32 Practice Problems give you a symptom and a board to try this on, and Reading a Cortex-M Hard Fault covers the crash case.