Intermediate Embedded Systems interview questions
150 questions with answers (EMB-151 to EMB-300). Try each one aloud before reading the answer.
Embedded C & Bit Manipulation
EMB-151 · How do you extract a field of width w starting at bit position p?
Shift the field down to bit 0, then mask off w bits.
uint32_t field = (x >> p) & ((1U << w) - 1U);This assumes w is less than 32, because shifting by the full type width is undefined.
EMB-152 · How do you update one field in a register without disturbing the other bits?
Use a read-modify-write: clear the field with an inverted mask, then OR in the new value, masked to the field width.
reg = (reg & ~(MASK << POS)) | ((val & MASK) << POS);EMB-153 · How do you check whether an unsigned integer is a power of two?
A power of two has exactly one bit set, so x & (x - 1) clears it to zero. The test is x != 0 && (x & (x - 1)) == 0; the zero check is needed because 0 would otherwise pass.
EMB-154 · How do you count the set bits in a word efficiently?
Brian Kernighan's method clears the lowest set bit on each pass, so the loop runs once per set bit.
unsigned n = 0;
while (x) { x &= x - 1U; n++; }Compilers may also provide __builtin_popcount.
EMB-155 · How do you convert a 32-bit value between little-endian and big-endian?
Swap the four bytes with shifts and masks. On Cortex-M the REV instruction (CMSIS __REV()) does it in one cycle.
y = (x >> 24) | ((x >> 8) & 0xFF00U) |
((x << 8) & 0xFF0000U) | (x << 24);EMB-156 · What is integer promotion and why does it matter in embedded C?
Operands smaller than int, such as uint8_t, are promoted to int before arithmetic. So ~(uint8_t)0x0F gives 0xFFFFFFF0 rather than 0xF0, and comparisons can change signedness. Cast the result back or mask it explicitly.
EMB-157 · What is structure padding and how can you reduce it?
The compiler inserts padding bytes so each member sits at its natural alignment. Ordering members from largest to smallest alignment minimises padding; {char; int; char;} is usually 12 bytes, but {int; char; char;} is 8.
EMB-158 · What does __attribute__((packed)) do, and what is the cost?
It removes padding so a struct matches an exact byte layout, such as a protocol header. Members may then be misaligned, which needs slower byte-wise access code and can fault on cores that do not support unaligned access, such as Cortex-M0.
EMB-159 · What is the difference between an inline function and a function-like macro?
An inline function is type-checked, evaluates each argument once and is visible to the debugger. A macro is plain text substitution, so SQUARE(i++) evaluates i++ twice and operator precedence can break it without full parentheses.
EMB-160 · Why are multi-statement macros wrapped in do { … } while (0)?
It makes the macro behave like a single statement, so it works correctly after an if without braces and requires a trailing semicolon. A plain { … } block breaks an if … else when the user adds a semicolon.
EMB-161 · What does the restrict qualifier mean?
It promises the compiler that, for the pointer's lifetime, the object it points to is accessed only through that pointer. The compiler can then keep values in registers and vectorise loops, but the behaviour is undefined if the promise is broken.
EMB-162 · How does fixed-point arithmetic work on an MCU without an FPU?
Values are stored as scaled integers, such as Q15 (1 sign bit, 15 fractional bits). Addition is ordinary integer addition, but multiplication needs a wider intermediate and a shift back.
int16_t q15_mul(int16_t a, int16_t b)
{ return (int16_t)(((int32_t)a * b) >> 15); }EMB-163 · How are unions used in embedded C?
A union lets several members share the same storage, which is used to view a register as a whole word or as fields, or to reinterpret bytes of a received frame. C allows reading a different member than was last written, but the result depends on endianness and layout.
Pointers, Memory & Linker Scripts
EMB-164 · What is the difference between const int *p, int *const p and const int *const p?
const int *p is a pointer to constant data: the data cannot be modified through p, but p can move. int *const p is a constant pointer: p cannot change, but the data can. const int *const p makes both constant.
EMB-165 · How does pointer arithmetic work?
Adding n to a pointer advances it by n × sizeof(*p) bytes, so p + 1 on a uint32_t * adds 4. Subtracting two pointers into the same array gives the number of elements between them, not bytes.
EMB-166 · How are arrays and pointers different?
An array name decays to a pointer to its first element in most expressions, but the array is a fixed block of storage: sizeof(arr) gives the whole array size and the name cannot be reassigned. A pointer is a separate variable whose sizeof is just the address size.
EMB-167 · How does startup code initialise .data and .bss?
It copies initial values from flash (the load address) to RAM and zeroes .bss, using symbols defined in the linker script.
uint32_t *src = &_sidata, *dst = &_sdata;
while (dst < &_edata) *dst++ = *src++;
for (dst = &_sbss; dst < &_ebss; ) *dst++ = 0;EMB-168 · What do the MEMORY and SECTIONS commands do in a GNU linker script?
MEMORY declares the named regions with origin, length and attributes, such as FLASH (rx) and RAM (rwx). SECTIONS maps input sections from object files into output sections and assigns each to a region, defining the final layout.
EMB-169 · What is the difference between VMA and LMA?
The load memory address (LMA) is where a section is stored in the image, usually flash. The virtual memory address (VMA) is where it lives at run time. For .data the LMA is in flash and the VMA is in RAM, which is why startup code copies it (> RAM AT> FLASH).
EMB-170 · How do you place a variable or function in a specific memory section?
Use a compiler attribute naming the section and add a matching output section in the linker script.
__attribute__((section(".ramfunc"))) void fast_isr(void);
__attribute__((section(".noinit"))) uint32_t reset_count;EMB-171 · What is a .noinit section used for?
It holds RAM variables that the startup code neither copies nor zeroes, so their values survive a warm reset. It is used for reset counters, crash logs and bootloader-to-application flags, and should be validated with a magic number.
EMB-172 · How can you detect a stack overflow on a microcontroller?
Fill the stack with a known pattern at startup and check the high-water mark later; place a canary word at the stack limit and test it; use the MPU to make a guard region below the stack fault; or use the stack-limit registers on Armv8-M cores.
EMB-173 · Why does memory alignment matter on Cortex-M?
Cortex-M0/M0+ fault on any unaligned access. Cortex-M3/M4/M7 support unaligned single loads and stores at a performance cost, but multiple and doubleword transfers such as LDM, STM and LDRD must still be aligned, otherwise a UsageFault occurs.
EMB-174 · What is a fixed-block memory pool?
An allocator that pre-divides a static buffer into equal-size blocks kept on a free list. Allocation and freeing take constant time, there is no external fragmentation, and exhaustion is easy to detect, so it suits real-time systems.
EMB-175 · When do you need a pointer to a pointer?
When a function must modify the caller's pointer itself, for example allocating a buffer or inserting at the head of a linked list. It is also used for arrays of strings such as char **argv.
void push(node_t **head, node_t *n) { n->next = *head; *head = n; }EMB-176 · What is the Memory Protection Unit (MPU)?
An optional Cortex-M unit that defines a small number of regions with access permissions, such as read-only or no-execute, and memory attributes. Violations raise a MemManage fault, which helps isolate RTOS tasks and catch stack overflows and null-pointer accesses.
Microcontroller Architecture (ARM Cortex-M)
EMB-177 · What is DMA and why is it useful?
Direct memory access lets a dedicated controller move data between peripherals and memory without the CPU. The CPU only sets up the transfer and handles a completion interrupt, which frees cycles, reduces interrupt load and supports high data rates.
EMB-178 · What are the common DMA transfer modes?
Peripheral-to-memory (ADC or UART receive), memory-to-peripheral (SPI or DAC transmit) and memory-to-memory. Circular mode restarts automatically at the end of the buffer, and double-buffer (ping-pong) mode lets the CPU process one half while DMA fills the other.
EMB-179 · What is the difference between MSP and PSP?
Cortex-M has two stack pointers. The main stack pointer (MSP) is used after reset and always in Handler mode. The process stack pointer (PSP) can be used by Thread-mode code, so an RTOS gives each task its own stack through PSP while exceptions use MSP.
EMB-180 · What are Thread mode, Handler mode and privilege levels on Cortex-M?
Handler mode runs exception handlers and is always privileged. Thread mode runs normal code and can be privileged or unprivileged, which is selected by the CONTROL register. Unprivileged code cannot access protected system registers, so an RTOS can protect its kernel.
EMB-181 · How deep are the pipelines of common Cortex-M cores?
Cortex-M0+ has a 2-stage pipeline, Cortex-M0, M3 and M4 have 3 stages (fetch, decode, execute), and Cortex-M7 has a 6-stage, dual-issue superscalar pipeline. Branches flush the pipeline, which costs a few cycles.
EMB-182 · What is bit-banding on Cortex-M3/M4?
A feature that maps each bit of the SRAM and peripheral bit-band regions to a full 32-bit word in an alias region, so one word write atomically sets or clears a single bit. The alias address = alias_base + (byte_offset × 32) + (bit × 4). It is not present on M0 or M7.
EMB-183 · Why does flash need wait states at high clock speeds?
Flash read access time is slower than a fast CPU cycle, so extra wait states are added per access as the clock rises. Prefetch buffers, instruction caches or vendor accelerators hide most of this penalty for sequential code.
EMB-184 · What cache coherency problem arises with DMA on a Cortex-M7?
The D-cache may hold stale data that the DMA has updated in RAM, or dirty data the DMA has not seen. Before DMA transmit, clean the cache lines; after DMA receive, invalidate them; or place DMA buffers in a non-cacheable MPU region. Buffers should be aligned to the 32-byte cache line.
EMB-185 · What is CMSIS?
The Common Microcontroller Software Interface Standard from ARM. CMSIS-Core provides standard register definitions, intrinsics such as __disable_irq() and NVIC functions; other parts include CMSIS-DSP, CMSIS-RTOS and CMSIS-DAP for debug probes.
EMB-186 · What is the difference between AHB and APB buses?
AHB is the high-performance bus for the CPU, memories and DMA, supporting pipelining and bursts. APB is a simpler, lower-power bus for slower peripherals such as UART, I2C and timers, connected through a bridge with its own prescaler.
EMB-187 · What is tightly coupled memory (TCM)?
Instruction and data RAM connected directly to the Cortex-M7 core, giving single-cycle, deterministic access without cache. It is used for time-critical ISRs, control loops and stacks.
EMB-188 · What are LDREX and STREX used for?
They implement atomic read-modify-write on Cortex-M3 and above. LDREX loads a value and marks exclusive access; STREX stores only if no other access broke the reservation and returns 0 on success, so the sequence is retried until it succeeds. Cortex-M0 lacks them.
EMB-189 · What does the xPSR register contain?
The program status register combines the APSR flags (N, Z, C, V and the saturation flag Q), the IPSR holding the current exception number, and the EPSR with the Thumb bit and interruptible-instruction state.
GPIO, Timers & PWM
EMB-190 · What is a watchdog timer?
A hardware timer that resets the system if software fails to refresh ("kick") it before it times out. It recovers the system from hangs, infinite loops and runaway code, and should be kicked only when the main work is known to be healthy.
EMB-191 · What is the difference between an independent watchdog and a window watchdog?
An independent watchdog runs from its own low-speed oscillator and resets if not refreshed before timeout, so it survives a main clock failure. A window watchdog also resets if refreshed too early, which catches code that is running too fast or stuck in a tight loop.
EMB-192 · How do you compute a timer's update frequency?
f_update = f_clk / ((PSC + 1) × (ARR + 1)). With a 72 MHz timer clock, PSC = 71 gives a 1 MHz tick, and ARR = 999 gives a 1 kHz (1 ms) update interrupt.
EMB-193 · How are PWM frequency, duty cycle and resolution related?
f_PWM = f_timer / (ARR + 1) and duty = CCR / (ARR + 1). Resolution is log₂(ARR + 1) bits, so a higher PWM frequency means fewer steps: a 64 MHz clock gives 10-bit resolution only up to 62.5 kHz.
EMB-194 · What is the difference between edge-aligned and center-aligned PWM?
Edge-aligned PWM counts up and resets, so all channels switch on together at the period start. Center-aligned PWM counts up and down, giving pulses symmetric about the period centre and half the frequency for the same ARR, with lower harmonics; it is preferred for motor control.
EMB-195 · What is dead time in complementary PWM?
A short delay inserted between turning off one switch of a half-bridge and turning on the other. It prevents both transistors from conducting at the same time (shoot-through), and is generated by advanced timers in hardware.
EMB-196 · How do you measure a signal's frequency with input capture?
Capture the counter value on two successive rising edges; the period in ticks is Δ = C₂ − C₁ using unsigned subtraction, so a single wrap is handled. Then f = f_timer / Δ. For very slow signals, count overflows too.
EMB-197 · Why use a GPIO bit set/reset register instead of read-modify-write on the output register?
A set/reset register such as BSRR changes chosen pins with one write, which is atomic. A read-modify-write on the output data register can be interrupted, and an ISR changing another pin on the same port would then have its change overwritten.
EMB-198 · How do you implement a simple software debounce?
Sample the pin at a fixed rate, for example every 5 ms from a timer, and accept a new state only after several consecutive matching samples.
if (raw != state) { if (++cnt >= 4) { state = raw; cnt = 0; } }
else cnt = 0;EMB-199 · How do you size an LED resistor on a GPIO pin?
R = (V_OH − V_f) / I_LED. For 3.3 V, a red LED with V_f ≈ 2.0 V and 10 mA, R = 1.3 / 0.01 = 130 Ω. Also check the pin and total port current limits in the datasheet.
EMB-200 · What is timer encoder mode?
A mode in which the timer counts up or down from two quadrature signals A and B of a rotary encoder. The count gives position and the direction comes from which channel leads, with ×4 resolution when both edges of both channels are counted.
EMB-201 · Why do GPIO inputs use Schmitt triggers?
A Schmitt trigger has separate rising and falling thresholds (hysteresis), so a slow or noisy edge produces one clean transition instead of several. This prevents multiple interrupts from one slow edge.
EMB-202 · How do you create an accurate microsecond delay on Cortex-M?
Use a hardware counter, such as the DWT cycle counter (DWT->CYCCNT, on M3 and above) or a free-running timer, and wait until the required ticks have passed. Empty busy loops depend on the clock, flash wait states and compiler optimisation.
ADC, DAC & Sensors Interfacing
EMB-203 · How do you convert an ADC code to a voltage?
V_in = code × V_ref / (2ᴺ − 1), or approximately code × V_ref / 2ᴺ. A 12-bit ADC with a 3.3 V reference reading 2048 gives about 1.65 V.
EMB-204 · What is ENOB?
The effective number of bits, which is the resolution an ideal ADC would need to match the measured noise and distortion: ENOB = (SINAD − 1.76) / 6.02. A 12-bit ADC measuring 62 dB SINAD has an ENOB of about 10 bits.
EMB-205 · How does oversampling increase ADC resolution?
Averaging many samples reduces uncorrelated noise. Each 4× oversampling followed by decimation adds about 1 bit, so 16× gives 2 extra bits. It works only if there is at least about 1 LSB of noise or dither on the signal.
EMB-206 · How do you sample several ADC channels continuously with little CPU load?
Configure scan mode for the channel sequence, trigger conversions from a timer and let DMA write the results into a circular buffer. The CPU processes data in half-transfer and transfer-complete interrupts.
EMB-207 · How does source impedance affect ADC sampling time?
The sample capacitor charges through the source and switch resistance with time constant τ = R·C. Reaching ½ LSB accuracy at N bits needs about (N + 1)·ln2·τ, so high-impedance sources need longer sampling time or an op-amp buffer.
EMB-208 · How do you measure a 12 V battery with a 3.3 V ADC?
Use a resistor divider with ratio below 3.3 / V_max. With R1 = 30 kΩ and R2 = 10 kΩ the ratio is 0.25, so 12 V becomes 3.0 V, with headroom up to 13.2 V. Large resistors save current but may need a capacitor or buffer for the ADC.
EMB-209 · What output does a 12-bit DAC give for a code of 1024 with a 3.3 V reference?
V_out = code × V_ref / 2ᴺ = 1024 × 3.3 / 4096 = 0.825 V. The output buffer, load and reference accuracy then limit the real value.
EMB-210 · What is the difference between DNL and INL?
Differential non-linearity is how far each code step deviates from the ideal 1 LSB; DNL below −1 LSB means missing codes. Integral non-linearity is the maximum deviation of the transfer curve from a straight line, which is the accumulated DNL.
EMB-211 · How do you perform two-point calibration of a sensor?
Measure raw readings r₁ and r₂ at two known values y₁ and y₂. Compute gain = (y₂ − y₁) / (r₂ − r₁) and offset = y₁ − gain·r₁, then correct each reading as y = gain·r + offset.
EMB-212 · How do you implement a moving-average filter efficiently?
Keep a ring buffer of N samples and a running sum: subtract the oldest sample, add the newest and divide by N. Choosing N as a power of two lets the divide become a shift.
sum += x - buf[i]; buf[i] = x; i = (i + 1) & (N - 1);
avg = sum >> LOG2N;EMB-213 · How do you interface a 4–20 mA sensor to an MCU ADC?
Pass the loop current through a precision shunt resistor; with 150 Ω, 4–20 mA becomes 0.6–3.0 V. A reading well below 4 mA indicates a broken wire or failed sensor, which is the advantage of the "live zero".
EMB-214 · What is ratiometric measurement?
Exciting a sensor, such as a potentiometer or bridge, from the same voltage used as the ADC reference. The result depends only on the ratio, so supply drift cancels out.
EMB-215 · Why trigger ADC conversions from a timer rather than in software?
A hardware trigger gives exactly uniform sampling intervals with no software jitter, which digital filters and FFTs need. It can also align samples with PWM, for example measuring motor current mid-period.
Interrupts & Exceptions
EMB-216 · What are the main rules for writing an ISR?
Keep it short; never block, wait or call printf or malloc; clear the interrupt source; use volatile for shared data and protect multi-byte data; defer heavy work to the main loop or a task; and use only ISR-safe RTOS API calls.
EMB-217 · Is declaring a shared ISR variable volatile enough to make it safe?
No. volatile forces real memory accesses but not atomicity. A 64-bit counter, or a read-modify-write such as count++, can still be torn or lose updates if the ISR runs in between, so use critical sections, atomic operations or single-word data.
EMB-218 · What is tail-chaining on Cortex-M?
If another interrupt is pending when an ISR finishes, the NVIC goes straight to the next handler without unstacking and restacking the registers. This cuts the switch between back-to-back interrupts to about 6 cycles on M3/M4.
EMB-219 · What is late arrival on Cortex-M?
If a higher-priority interrupt arrives while the core is still stacking registers for a lower-priority one, the core uses the same stack frame and runs the higher-priority handler first. This avoids extra latency for urgent interrupts.
EMB-220 · Which registers does Cortex-M stack automatically on exception entry?
Eight words: R0–R3, R12, LR, PC and xPSR. With the FPU active it can also reserve S0–S15 and FPSCR, which are filled lazily only if the handler uses floating point. R4–R11 are callee-saved and preserved by the compiler if used.
EMB-221 · What is EXC_RETURN?
A special value loaded into LR on exception entry. Branching to it returns from the exception, and its low bits say which stack and mode to return to: 0xFFFFFFF9 means Thread mode using MSP, 0xFFFFFFFD means Thread mode using PSP, and 0xFFFFFFF1 means Handler mode.
EMB-222 · What is the difference between preemption priority and subpriority on Cortex-M?
The priority grouping setting splits each priority field into a group (preemption) priority and a subpriority. Only a higher group priority can preempt a running ISR; the subpriority only decides which of several pending interrupts with equal group priority runs first.
EMB-223 · What do PRIMASK, FAULTMASK and BASEPRI do?
PRIMASK = 1 masks all exceptions with configurable priority, leaving NMI and HardFault. FAULTMASK also masks HardFault, leaving only NMI. BASEPRI masks only interrupts at or below a chosen priority level, so urgent ISRs still run; it is not available on Armv6-M.
EMB-224 · What are SVCall and PendSV used for in an RTOS?
SVC is a software interrupt instruction that lets unprivileged code request kernel services and is often used to start the first task. PendSV is a pendable exception set to the lowest priority, so the context switch runs only after all other ISRs have finished.
EMB-225 · What is deferred interrupt processing?
Splitting interrupt handling into a minimal ISR that captures data and clears the source, and a task or main-loop handler that does the slow processing. It keeps interrupt latency low; Linux calls these the top half and bottom half.
EMB-226 · Why can an interrupt fire twice even though the ISR clears its flag?
Clearing the flag as the last instruction may not reach the peripheral, through the bus write buffer, before the exception returns, so the NVIC sees it still pending and re-enters. Clear the flag early in the ISR, or read the register back or use a DSB after clearing.
EMB-227 · What fault exceptions do Cortex-M3/M4 provide?
MemManage (MPU violations), BusFault (bus errors on access or fetch), UsageFault (undefined instruction, invalid state, unaligned or divide-by-zero if enabled) and HardFault. The first three are configurable and escalate to HardFault if disabled. Cortex-M0 has only HardFault.
EMB-228 · How do you read a multi-byte variable shared with an ISR safely?
Take a copy inside a short critical section so the ISR cannot change it halfway through.
uint32_t pm = __get_PRIMASK(); __disable_irq();
uint64_t t = ticks64;
__set_PRIMASK(pm);Restoring PRIMASK, rather than always re-enabling, keeps the code safe if interrupts were already disabled.
Communication Protocols (UART, SPI, I2C, CAN, USB)
EMB-229 · How do UART, SPI and I2C compare?
UART is asynchronous, uses 2 wires (TX, RX) and is point-to-point. SPI is synchronous, uses 4 wires, is full-duplex and fast, and needs one chip select per slave. I2C is synchronous, uses 2 wires, supports multiple masters and addressed devices, and is slower.
EMB-230 · What are the four SPI modes?
They combine clock polarity (CPOL, the idle level of SCLK) and clock phase (CPHA, which edge samples data). Mode 0 is CPOL = 0, CPHA = 0; Mode 1 is 0, 1; Mode 2 is 1, 0; Mode 3 is 1, 1. Master and slave must use the same mode.
EMB-231 · How are I2C START and STOP conditions signalled?
START is SDA going low while SCL is high; STOP is SDA going high while SCL is high. During data transfer SDA may change only while SCL is low, so these two transitions are unique markers. A repeated START begins a new transfer without releasing the bus.
EMB-232 · What is I2C clock stretching?
A slave holds SCL low after a byte to pause the master until it is ready to continue. The master must detect that SCL has not risen, which some simple or bit-banged masters do not support.
EMB-233 · How do you choose I2C pull-up resistor values?
R_min = (V_DD − V_OL) / I_OL, about (3.3 − 0.4) / 3 mA ≈ 967 Ω. R_max = t_r / (0.8473 × C_b); for 400 kHz (t_r = 300 ns) and 100 pF, R_max ≈ 3.5 kΩ. A 2.2 kΩ pull-up fits both limits.
EMB-234 · How does CAN arbitration work?
All nodes transmit their identifiers bit by bit; a dominant bit (0) overrides a recessive bit (1). A node that sends recessive but reads dominant stops transmitting, so the lowest identifier wins without corrupting the frame. This is non-destructive bitwise arbitration.
EMB-235 · What fields make up a classical CAN data frame?
Start of frame, an 11-bit (standard) or 29-bit (extended) identifier, the RTR bit, a control field with the 4-bit DLC, 0–8 data bytes, a 15-bit CRC with delimiter, the ACK slot and delimiter, and a 7-bit end of frame.
EMB-236 · Why does a CAN bus need 120 Ω termination at both ends?
The resistors match the cable's characteristic impedance and stop reflections that would corrupt bits. With two 120 Ω terminators in parallel, a meter between CAN_H and CAN_L on an unpowered bus reads about 60 Ω.
EMB-237 · What is the UART baud-rate error with a 16 MHz clock, 16× oversampling and 115200 baud?
The ideal divisor is 16 MHz / (16 × 115200) ≈ 8.68. Rounding to 9 gives 111,111 baud, an error of about −3.5%, which is too high for reliable 8N1. Use 8× oversampling, a fractional baud generator or a baud-friendly crystal.
EMB-238 · What happens during USB enumeration?
When a device attaches, the host resets it, reads the device descriptor at address 0, assigns a unique address and reads the configuration, interface and endpoint descriptors. It then loads a matching driver and selects a configuration.
EMB-239 · What are the four USB transfer types?
Control (setup and enumeration, guaranteed delivery), bulk (large data with error correction but no bandwidth guarantee), interrupt (small, periodic, bounded latency, such as HID) and isochronous (guaranteed bandwidth with no retries, such as audio).
EMB-240 · What is UART hardware flow control?
RTS and CTS lines let each receiver tell the sender to pause when its buffer is nearly full. It prevents overrun errors at high baud rates, especially when the receiver cannot service its FIFO in time.
RTOS Concepts
EMB-241 · What is the difference between an RTOS and a general-purpose OS?
An RTOS gives deterministic, bounded response times with strict priority preemption and a small footprint. A GPOS such as desktop Linux optimises for throughput, fairness and features, so latency can vary widely.
EMB-242 · What is the difference between a binary and a counting semaphore?
A binary semaphore holds 0 or 1 and is typically used to signal an event from an ISR to a task. A counting semaphore holds values up to N, so it can count queued events or manage a pool of N identical resources.
EMB-243 · What is deadlock and how do you prevent it?
Deadlock happens when tasks wait forever for resources held by each other. It needs mutual exclusion, hold-and-wait, no preemption and circular wait. Prevent it by always acquiring locks in a fixed global order, using timeouts or holding only one lock at a time.
EMB-244 · What is starvation in an RTOS?
A low-priority task never gets CPU time because higher-priority tasks are always ready. It is avoided by making high-priority tasks block regularly, using correct priority assignment and avoiding busy-wait loops.
EMB-245 · What are event flags (event groups)?
A set of bits in a kernel object that tasks can set, clear and wait on, either for any bit or all bits. They let one task wait for several conditions at once, such as "Wi-Fi connected AND sensor ready".
EMB-246 · Why do some RTOS calls have special ISR versions, such as xQueueSendFromISR?
An ISR cannot block, and the kernel must not switch context in the middle of an ISR. The ISR variants never wait; instead they report whether a higher-priority task was woken, so the ISR can request a context switch on exit.
EMB-247 · How do you size a task's stack?
Estimate the deepest call chain: locals, saved registers, library calls such as printf, and any exception frame stacked on it. Then measure with stack painting or the RTOS high-water-mark function under worst-case load and add a margin, often around 20–50%.
EMB-248 · What is jitter in a real-time system?
The variation in timing of a periodic event, such as the start time of a control task from one period to the next. It comes from interrupt masking, higher-priority tasks and cache effects, and it degrades control loops and sampling.
EMB-249 · What are RTOS software timers?
Kernel-managed timers that call a callback after a delay or periodically, usually from a timer service task rather than an ISR. Callbacks must be short and must not block, because they delay every other timer.
EMB-250 · What are direct-to-task notifications in FreeRTOS?
A lightweight mechanism in which each task has a notification value that an ISR or task can set, increment or OR. It can replace a binary or counting semaphore or event group for one receiving task, and is faster and uses less RAM.
EMB-251 · What is rate-monotonic scheduling?
A fixed-priority policy in which tasks with shorter periods get higher priorities. For n independent periodic tasks with deadlines equal to periods, all deadlines are guaranteed if U = Σ Cᵢ/Tᵢ ≤ n(2^(1/n) − 1), which tends to about 69.3% for large n.
EMB-252 · What is tickless idle?
An RTOS mode that stops the periodic tick when only the idle task is ready, programs a timer for the next scheduled wake-up and sleeps until then. On wake-up the kernel corrects its tick count, saving power from needless tick interrupts.
Bootloaders & Firmware Updates
EMB-253 · How does a Cortex-M bootloader jump to the application?
It reads the application's vector table: word 0 is the initial MSP and word 1 is the reset handler. It sets VTOR, loads the MSP and branches to the reset handler.
uint32_t *vt = (uint32_t *)APP_BASE;
SCB->VTOR = APP_BASE;
__set_MSP(vt[0]);
((void (*)(void))vt[1])();EMB-254 · Why must the application's vector table be relocated?
After a jump, the application's interrupts must use its own handlers, not the bootloader's. Setting VTOR to the application's base address does this, and the base must meet VTOR's alignment requirement. On Cortex-M0 without VTOR, the vectors are copied to RAM and RAM is remapped to address 0.
EMB-255 · How is flash partitioned between the bootloader and the application?
Each image gets its own linker script: the bootloader starts at the flash base and the application starts at a sector-aligned offset, such as 0x0800_8000. The partitions also reserve space for a download slot and configuration data.
EMB-256 · What should a bootloader clean up before jumping to the application?
Disable interrupts, stop SysTick, de-initialise used peripherals and DMA, clear pending NVIC interrupts and restore default clocks if the application expects them. Leftover state can cause spurious interrupts before the application installs its handlers.
EMB-257 · How can a running application request entry into the bootloader?
It writes a magic value to a .noinit RAM location or a backup register, then triggers a software reset. The bootloader checks the flag early, clears it and stays in update mode. A held button or boot pin is a common hardware alternative.
EMB-258 · Why is CRC-32 preferred over a simple additive checksum for image validation?
An additive checksum misses reordered bytes and many multi-bit errors. A CRC-32 detects all single-bit and burst errors up to 32 bits and most others. Neither proves authenticity; that needs a cryptographic signature.
EMB-259 · What does a firmware image header usually contain?
A magic number, header version, image version, load address, image size, a hash or CRC, and often a cryptographic signature and hardware compatibility ID. The bootloader parses it to decide whether the image is valid and allowed.
EMB-260 · What is anti-rollback protection?
A check that refuses to boot images older than a stored minimum version, held in a monotonic counter or OTP fuses. It stops attackers from installing an older, correctly signed version with a known vulnerability.
EMB-261 · How do you make a firmware update power-fail safe?
Never overwrite the only working image: download into a separate slot, verify it, then switch with an atomic flag update or a resumable swap that records progress. The old image stays bootable until the new one has run and confirmed itself.
EMB-262 · What is a delta (differential) firmware update?
Sending only a binary patch that turns the old image into the new one, which the device applies locally. It greatly reduces download size and radio energy but needs the exact base image and extra flash or RAM to apply the patch.
EMB-263 · What is MCUboot?
An open-source secure bootloader for 32-bit MCUs, used with Zephyr and other RTOSes. It verifies signed images and supports update strategies such as swapping primary and secondary slots with revert on failure.
EMB-264 · Why must flash write endurance be considered when storing data?
Each flash sector tolerates only a limited number of erase cycles, often around 10,000 for MCU internal flash (check the datasheet). Logging frequently to one sector wears it out, so use wear levelling, larger buffers or an external EEPROM or FRAM.
Low-Power Design
EMB-265 · How do you compute the average current of a duty-cycled device?
I_avg = (I_active·t_active + I_sleep·t_sleep) / T. A node that draws 10 mA for 10 ms every second and 5 µA otherwise averages about 0.1 mA + 0.005 mA ≈ 105 µA.
EMB-266 · What is the "race to sleep" strategy?
Run the task quickly at full speed and then enter deep sleep as soon as possible, instead of running slowly for longer. It usually saves energy because sleep current is far lower than the static and peripheral current that flows while awake.
EMB-267 · Why should unused GPIO pins be configured carefully?
A floating CMOS input can sit near the switching threshold, causing both input transistors to conduct and drawing extra current. Set unused pins to analog mode, or to a defined level with a pull resistor, to minimise leakage.
EMB-268 · What is dynamic voltage and frequency scaling (DVFS)?
Lowering the core voltage and clock when full performance is not needed. Because dynamic power scales with V²·f, a modest voltage reduction gives large savings. Voltage must rise before frequency is increased.
EMB-269 · What are power domains and RAM retention?
The chip is split into regions that can be powered off independently. In deep sleep, retention keeps selected RAM banks or registers powered at low voltage, so the context survives without the full current of running memory.
EMB-270 · How does clock frequency affect energy per operation?
Dynamic power rises roughly linearly with frequency, but the time per task falls equally, so dynamic energy per task stays roughly constant at a fixed voltage. Static and peripheral energy grows the longer the chip is awake, so higher speed at the same voltage often uses less total energy.
EMB-271 · How do you measure the current of a low-power device accurately?
Use an instrument with a wide dynamic range, such as a power analyser, source-measure unit or dedicated power profiler, because current swings from nanoamps to tens of milliamps. Disconnect the debugger, which keeps debug logic powered, and capture the full wake-up cycle.
EMB-272 · What is Cortex-M sleep-on-exit?
Setting the SLEEPONEXIT bit in the System Control Register makes the core return to sleep automatically after an ISR finishes, without returning to Thread mode. It suits fully interrupt-driven applications and saves the unstack and restack overhead.
EMB-273 · Why do MCUs provide low-power peripherals such as LPUART and LPTIM?
They run from low-speed clocks, such as 32.768 kHz, and stay active in stop modes. They can receive data or count events and wake the CPU only when needed, avoiding a high-speed clock running all the time.
EMB-274 · What commonly causes higher-than-expected sleep current?
An attached debugger or enabled debug-in-sleep bits, floating inputs, pull-ups fighting external levels, regulators with high quiescent current, LEDs or sensors left powered, and peripherals whose clocks were not gated.
EMB-275 · What must firmware handle in an energy-harvesting system?
Supply power is intermittent and small, so energy is stored in a capacitor or battery. Firmware must check the stored voltage before tasks, save state to non-volatile memory before the supply collapses, and run in short bursts.
EMB-276 · How can an RTOS-based system manage peripheral power cleanly?
Give each peripheral a power manager with reference counting: drivers request the peripheral or clock when they need it and release it afterwards. The idle hook then chooses the deepest sleep mode allowed by the current requests and the next timer deadline.
Debugging & Testing
EMB-277 · How do you find the cause of a HardFault on Cortex-M?
Read the stacked exception frame to get the faulting PC and LR, then check the fault status registers CFSR and HFSR, and MMFAR or BFAR for the faulting address. Look up the PC in the map or disassembly to find the instruction.
EMB-278 · What are SWO and ITM?
The Instrumentation Trace Macrocell (ITM) on Cortex-M3 and above lets firmware write log data to stimulus ports. It is sent out over the single Serial Wire Output (SWO) pin. This gives fast printf-style tracing without stopping the CPU.
EMB-279 · What is ETM trace?
The Embedded Trace Macrocell records the instruction execution history in real time and streams it through a trace port to a capable probe. It lets you reconstruct exactly what code ran before a crash, without breakpoints.
EMB-280 · How do you unit-test driver code that touches hardware registers?
Put a thin hardware abstraction layer between logic and registers, and replace it with mocks or fake register structs in host tests. Tests can then preset status bits and check the values the code writes.
typedef struct { volatile uint32_t SR, DR; } uart_regs_t;
uart_regs_t fake = { .SR = TXE_BIT };
uart_init(&fake);EMB-281 · What are statement, branch and MC/DC coverage?
Statement coverage checks that every line executed. Branch coverage checks that every decision took both outcomes. MC/DC shows that each condition in a decision independently affects the outcome, and is required for the highest safety levels.
EMB-282 · What is test-driven development in embedded work?
Writing a failing unit test first, then the minimum code to pass, then refactoring. In embedded work it is done mostly on the host with hardware mocked, which gives fast feedback and modular, testable drivers.
EMB-283 · What is fault-injection testing?
Deliberately introducing faults, such as corrupted messages, sensor failures, bit flips, brown-outs or stuck tasks, to verify that the system detects them and reaches a safe state. Safety standards such as ISO 26262 require it.
EMB-284 · How do you measure a function's execution time in cycles on Cortex-M3 and above?
Enable the DWT cycle counter and read it before and after the code.
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->CYCCNT = 0; DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
uint32_t t0 = DWT->CYCCNT; work(); uint32_t dt = DWT->CYCCNT - t0;EMB-285 · How do you capture crash information from devices in the field?
In the fault handler, save the stacked registers, fault status registers and a short stack trace to a .noinit RAM area or flash, then reset. On the next boot, read and upload or log the record for analysis.
EMB-286 · How do you debug timing problems that disappear when you add breakpoints or printf?
Use non-intrusive methods: toggle GPIO pins and watch them on a logic analyser, use ITM or ETM trace, or log into a RAM buffer read later. Breakpoints and slow logging change the timing that causes the bug.
EMB-287 · Why use continuous integration for firmware?
Every commit is built for all targets, run through static analysis and unit tests, and ideally flashed onto test hardware for automated tests. Regressions are caught early, and builds become reproducible.
EMB-288 · Why compile firmware with warnings such as -Wall -Wextra treated as errors?
Warnings often point to real bugs: implicit conversions, uninitialised variables, missing return values, sign comparisons and format mismatches. Treating them as errors keeps the codebase clean.
Embedded Linux, Safety & Security
EMB-289 · What is the typical boot sequence of an embedded Linux board?
Boot ROM → first-stage loader (such as U-Boot SPL) that initialises DRAM → U-Boot → Linux kernel with the device tree → mounting the root file system → init (systemd, BusyBox init) → user applications.
EMB-290 · What is a cross-compiler toolchain?
A compiler, assembler, linker and C library that run on the host but produce code for the target, such as arm-none-eabi-gcc for bare-metal Cortex-M or aarch64-linux-gnu-gcc for 64-bit ARM Linux. The prefix names the architecture, OS and ABI.
EMB-291 · How does a Linux character driver expose a device?
It registers a struct file_operations with callbacks such as open, read, write, unlocked_ioctl and release, and creates a device node under /dev. User programs then use ordinary file system calls on it.
EMB-292 · How should user-space programs control GPIO on modern Linux?
Through the GPIO character device (/dev/gpiochipN) using libgpiod, which supports line requests, events and multiple lines atomically. The older sysfs /sys/class/gpio interface is deprecated.
EMB-293 · What is PREEMPT_RT?
A set of Linux kernel changes that make most of the kernel preemptible, turn interrupt handlers into threads and add priority inheritance to locks. It greatly reduces worst-case latency so Linux can meet many soft and firm real-time needs.
EMB-294 · What is HARA in ISO 26262?
Hazard Analysis and Risk Assessment: identifying vehicle-level hazards and rating each by Severity (S), Exposure (E) and Controllability (C). The combination determines the ASIL and leads to safety goals.
EMB-295 · What is a safe state?
An operating mode with no unreasonable risk that the system enters when it detects a fault, such as motor torque off, valves closed or limp-home mode. Reaching it must happen within the fault tolerant time interval.
EMB-296 · What is freedom from interference?
The requirement that a lower-integrity software component cannot corrupt a higher-integrity one through memory, timing or communication. It is achieved with MPU or MMU partitioning, time budgets and watchdogs, and end-to-end message protection.
EMB-297 · Give examples of what MISRA C restricts.
Dynamic heap allocation, recursion, goto in most cases, implicit conversions between essential types such as signed and unsigned, unions for type punning, unreachable code, side effects in conditions and reliance on undefined or unspecified behaviour.
EMB-298 · What is a secure element?
A tamper-resistant chip that stores keys and performs cryptographic operations, such as signing or ECDH, inside itself. The private key never leaves the device, even if the main MCU firmware is compromised.
EMB-299 · What is a chain of trust?
A sequence in which an immutable root (ROM code and a key hash in OTP) verifies the first bootloader, which verifies the next stage, through to the application. Every executing image is authenticated by an already trusted stage.
EMB-300 · What is debug port lockout or readout protection?
An option-byte or fuse setting that disables or restricts SWD/JTAG access and flash readout, so attackers cannot dump firmware or keys. Higher levels may be irreversible, so they are set only on production units.
Other levels: Basic · Advanced · Tricky · All Embedded Systems questions