An ISR sets a shared 32-bit `volatile uint32_t event_flags` and the main loop does `if (event_flags & 0x2) { event_flags &= ~0x2; }`. On a Cortex-M4 the flag is occasionally lost even though the variable is `volatile`. What is the precise root cause?
- A. `volatile` does not force the variable into a CPU register, so the compiler re-reads stale memory
- B. The main loop's `event_flags &= ~0x2` is a non-atomic read-modify-write; an ISR firing between the load and store overwrites the ISR's newly-set bit ✓
- C. Cortex-M4 lacks cache coherency, so the ISR write never reaches the main-loop's view of memory
- D. `volatile` disables the write buffer, so the store is dropped under back-to-back interrupts
Correct answer: B. The `&=` compiles to load-modify-store; if the ISR runs between the load and the store, its bit set is clobbered when the stale-modified value is written back, which volatile cannot prevent.
A high-priority task H is blocked waiting on a mutex held by a low-priority task L, while a medium-priority task M (which never touches the mutex) is CPU-bound and keeps preempting L. H misses its deadline. Under a priority-inheritance mutex, what specifically happens to break this?
- A. L's priority is temporarily raised to H's priority while it holds the mutex, so M can no longer preempt L, letting L finish and release quickly ✓
- B. M is temporarily demoted below L until the mutex is released
- C. H's priority is lowered to L's so all three tasks run round-robin
- D. The scheduler boosts M to H's priority to flush it out of the critical section faster
Correct answer: A. Priority inheritance raises the mutex holder (L) to the priority of the highest waiter (H) for the duration it holds the lock, so intermediate task M can no longer preempt it and the unbounded inversion is bounded.
On a Cortex-M7 with D-cache enabled, the CPU fills a TX buffer in a cacheable region, then starts a memory-to-peripheral DMA from that buffer. The peripheral transmits stale bytes. Assuming write-back caching, what is the correct fix?
- A. Invalidate the cache lines covering the buffer before starting the DMA
- B. Clean (flush) the cache lines covering the buffer before starting the DMA, ensuring the buffer is cache-line aligned and padded ✓
- C. Disable interrupts around the DMA start to prevent reordering
- D. Insert a DSB barrier before the DMA start; the barrier flushes dirty lines
Correct answer: B. For CPU→peripheral transfers the dirty CPU-written data sits in cache, so you must clean/flush those lines to main memory before the DMA reads them; alignment/padding avoids corrupting adjacent data on partial lines.
After a crash with no debugger attached, you recover from RAM: LR (EXC_RETURN) = 0xFFFFFFFD, and the stacked frame shows PC pointing into a valid function but the fault was a precise BusFault. What does EXC_RETURN 0xFFFFFFFD tell you about where to read the stacked registers?
- A. The exception used the FPU extended frame; read from MSP
- B. Return to Thread mode using the Process Stack Pointer (PSP), so the stacked R0-R3, R12, LR, PC, xPSR are on the PSP ✓
- C. Return to Handler mode using MSP; the frame is on the MSP
- D. The value is invalid; EXC_RETURN must be 0xFFFFFFF9 for a valid frame
Correct answer: B. EXC_RETURN 0xFFFFFFFD means return to Thread mode with PSP and the basic (non-FP) frame, so the stacked exception context must be read from the PSP, not the MSP.
A single-producer/single-consumer lock-free ring buffer uses `head` (written by ISR producer) and `tail` (written by task consumer). On a weakly-ordered Cortex-A core, the consumer sometimes reads a slot before the producer's data write is visible. Where must a barrier go, and why?
- A. The producer must write the data slot, then execute a write barrier (DMB), then publish the incremented `head`, so data is visible before the index that exposes it ✓
- B. Only the consumer needs a barrier, after reading `head`
- C. Barriers are unnecessary if `head` and `tail` are `volatile`
- D. Wrap both index updates in a spinlock; barriers cannot help SPSC buffers
Correct answer: A. The producer must ensure the data store is globally visible before the head-index store that publishes it, which requires a write barrier between the payload write and the index update on a weakly-ordered core.
You must clear bit 3 of a peripheral control register that also has a write-1-to-clear (W1C) interrupt-status field in the same 32-bit word. Doing `REG |= (1<<3)` on the whole word is dangerous. Why?
- A. `|=` is atomic so it is actually safe here
- B. The read-modify-write reads the currently-set W1C status bits and writes them back as 1, inadvertently clearing pending interrupt flags ✓
- C. Writing to a control register always triggers a bus fault on partial words
- D. The compiler will optimize away the load since the register is not volatile
Correct answer: B. A read-modify-write reads any currently-asserted W1C status bits as 1 and writes them back, which acknowledges/clears those interrupts as an unintended side effect; such registers need field-isolated or byte-wise access per the datasheet.
A firmware image does OTA via A/B partitions. After flashing slot B and rebooting into it, the device must decide whether the update is good. Which mechanism gives atomic rollback if slot B boots but fails a health check?
- A. Erase slot A immediately after flashing B so there is no ambiguity
- B. Boot B with a one-shot 'trial' flag; B must actively confirm (set 'confirmed') within a health window, else the bootloader reverts to A on the next reset ✓
- C. Compute a CRC of B before boot; if it matches, mark B permanent
- D. Copy B over A during boot so both slots are identical
Correct answer: B. A trial/pending flag that the new image must explicitly confirm after passing health checks lets the bootloader automatically fall back to the known-good slot if the confirmation never arrives, giving atomic rollback.
A battery sensor node wakes every second to sample and drains far faster than budgeted. Measured current in 'sleep' is ~1.2 mA instead of the expected few µA. Which cause is most consistent with this symptom?
- A. The core enters WFI but a peripheral clock (e.g., a running timer or unstopped ADC/UART) and its clock domain were left ungated, keeping a high-power domain active ✓
- B. WFI is the wrong instruction; WFE would reach a deeper mode
- C. The MCU cannot reach stop mode because interrupts are globally disabled
- D. Flash wait states are too high, increasing active current
Correct answer: A. A residual ~1 mA floor during 'sleep' typically means a peripheral/clock domain (timer, ADC, UART, or an unstopped oscillator) was not gated, so the part never truly entered the low-power state despite executing WFI.
Two tasks each need mutex A and mutex B. Task1 locks A then B; Task2 locks B then A. Occasionally the system hangs with both blocked. Besides using timeouts, what is the canonical structural fix?
- A. Convert both mutexes to counting semaphores with count 2
- B. Enforce a global lock-ordering discipline so every task always acquires A before B ✓
- C. Raise Task1's priority above Task2 so it always wins
- D. Disable preemption while any mutex is held
Correct answer: B. A circular wait requires two tasks to acquire the same locks in opposite orders; imposing a single consistent global acquisition order eliminates the cycle and thus the deadlock by construction.
A task set on a single core has periods/WCETs: T1(P=10,C=3), T2(P=15,C=4), T3(P=30,C=8), scheduled rate-monotonic (shorter period = higher priority). Total utilization U = 0.3+0.267+0.267 = 0.834. What can you conclude about schedulability?
- A. U < 1 so it is definitely schedulable under RMS
- B. U = 0.834 exceeds the n=3 Liu-Layland bound (~0.780), so the sufficient test fails; schedulability is inconclusive and needs an exact response-time analysis ✓
- C. U > 0.780 so it is definitely NOT schedulable
- D. RMS cannot schedule three tasks; use EDF
Correct answer: B. The Liu-Layland utilization bound is only sufficient, not necessary; since U exceeds the ~0.78 bound for 3 tasks you cannot conclude either way and must run an exact response-time (worst-case) analysis.
An ARM Cortex-M firmware hard-faults intermittently only with optimization enabled, near a struct accessed via a cast pointer. Most likely cause?
- A. Stack overflow only at -O0
- B. Unaligned memory access to a 32-bit value the compiler assumed aligned ✓
- C. Flash wear-out
- D. Interrupt vector table missing
Correct answer: B. Optimized code may emit word accesses assuming alignment; a misaligned pointer cast then triggers an alignment/usage fault on Cortex-M.
An ISR sets a global int flag that main polls, but with -O2 main never sees the update even though the ISR runs. Fix?
- A. Declare the flag static
- B. Declare the flag volatile so the compiler re-reads it from memory ✓
- C. Increase the optimization level
- D. Move main() logic into the ISR
Correct answer: B. Without volatile the compiler may cache the flag in a register in the polling loop; volatile forces a memory re-read each iteration.
You must guarantee a write to one peripheral register completes before reading another on Cortex-M. Which barrier is appropriate?
- A. NOP
- B. DMB/DSB (data memory/synchronization barrier) ✓
- C. WFI
- D. SVC
Correct answer: B. A DMB or DSB memory barrier enforces ordering/completion of memory accesses when required for peripheral sequencing.
Firmware using flash-emulated EEPROM starts corrupting data after months in the field. Most likely root cause?
- A. Baud rate drift
- B. Flash endurance/wear exhaustion from too many erase cycles on one sector ✓
- C. Watchdog too long
- D. I2C address conflict
Correct answer: B. Flash cells have limited erase/write endurance; without wear leveling, frequent writes to one sector exhaust it and cause corruption.
An interrupt-driven ring buffer (ISR increments head, main increments tail) occasionally loses bytes at high data rates. Most likely subtle bug?
- A. Tail is signed
- B. The full/empty check races because index updates or wrap aren't handled atomically/correctly ✓
- C. The buffer is in flash
- D. The UART is 8N2
Correct answer: B. Lock-free single-producer/consumer ring buffers require careful atomic index ordering; incorrect full/empty checks or non-atomic updates drop or overwrite data.
An RTOS task occasionally misses its deadline under load, and adding a lower-priority task made it worse. Best mitigation for the underlying priority inversion?
- A. Round-robin time slicing
- B. Priority inheritance on the shared mutex ✓
- C. Disabling the scheduler
- D. Increasing tick frequency only
Correct answer: B. Priority inheritance temporarily raises the mutex holder's priority to that of the highest waiter, bounding the inversion.
A sensor read over SPI works at 1 MHz but returns garbage at 8 MHz, with degraded signals on a scope. Most likely cause?
- A. Wrong I2C address
- B. Signal integrity issues (trace length, capacitance, missing termination) exceeding slave timing at higher clock ✓
- C. The MCU ran out of RAM
- D. The compiler optimized the read
Correct answer: B. At higher SPI clocks, PCB parasitics and inadequate termination degrade edges beyond the slave's setup/hold timing, corrupting data.
During a firmware over-the-air update, power loss mid-write can brick the device. Which design prevents this?
- A. Single-bank flash overwrite in place
- B. Dual-bank (A/B) flash with a bootloader that switches only after full verification ✓
- C. Writing directly over the running image
- D. Disabling the watchdog during update
Correct answer: B. Dual-bank A/B updates keep a valid image intact and switch only after the new image is fully written and verified, making updates power-fail safe.
A Cortex-M enters a fault only sometimes when a specific FreeRTOS task runs, and configASSERT points to stack. Most probable cause?
- A. Task stack overflow corrupting adjacent memory or the TCB ✓
- B. Flash too small
- C. Wrong endianness
- D. UART parity error
Correct answer: A. An undersized task stack overflows into neighboring memory depending on call depth and ISR nesting, causing sporadic faults.
You need microsecond-accurate, jitter-free periodic pulses on a pin while the CPU handles other work. Best approach?
- A. A software delay loop in main
- B. A hardware timer in output-compare/PWM mode driving the pin directly ✓
- C. Bit-banging inside a low-priority RTOS task
- D. Polling a GPIO in a tight loop
Correct answer: B. A hardware timer in output-compare/PWM mode toggles the pin in hardware with deterministic timing, immune to CPU load and interrupt jitter.
On a Cortex-M, an ISR writes to a peripheral register then the main code disables the peripheral immediately after, but the write seems lost. What mechanism most likely explains this?
- A. Cache coherency on the MCU core
- B. Write buffering/store ordering; a DSB/memory barrier or read-back is needed to ensure the write completed ✓
- C. Stack corruption
- D. Incorrect endianness
Correct answer: B. The write buffer may not have drained; a memory barrier (DSB) or register read-back ensures the peripheral write completes before subsequent actions.
You measure that an interrupt occasionally has ~50 microseconds of extra latency on a Cortex-M. Which is the most likely firmware cause?
- A. Flash is nearly full
- B. Long critical sections that disable interrupts, or a higher/equal priority ISR running ✓
- C. Using volatile variables
- D. The linker placed code in RAM
Correct answer: B. Interrupt latency jitter typically comes from interrupts being disabled in critical sections or another same/higher-priority handler running.
A struct mapped over a memory-mapped peripheral works with -O0 but breaks at -O2. What is the most likely root cause?
- A. The optimizer inlined main()
- B. Register fields not declared volatile, so the compiler reorders or eliminates accesses ✓
- C. The heap is too small
- D. printf is not reentrant
Correct answer: B. Peripheral registers must be volatile; without it, aggressive optimization reorders/coalesces or removes the required hardware accesses.
Two tasks in an RTOS occasionally deadlock. Task A locks mutex X then Y; Task B locks Y then X. What is the standard prevention technique?
- A. Increase both task priorities equally
- B. Enforce a global lock ordering so all tasks acquire mutexes in the same order ✓
- C. Use larger stacks
- D. Disable the scheduler tick
Correct answer: B. Consistent global lock ordering prevents the circular-wait condition required for deadlock.
A battery device draws far more sleep current than expected. After entering STOP mode, which oversight most commonly causes this?
- A. The watchdog is enabled
- B. Floating GPIO inputs or peripherals/clocks left enabled sinking current ✓
- C. Using an RTOS
- D. The flash wait states are too high
Correct answer: B. Floating inputs can oscillate and draw current, and leaving peripherals/clocks on defeats low-power modes, raising sleep current.
You need to guarantee a hard real-time deadline of 100 microseconds for a control loop. Which implementation choice is most robust?
- A. A high-priority preemptive interrupt/timer-driven handler with bounded execution time ✓
- B. Polling inside a low-priority background task
- C. A delay loop calibrated at boot
- D. Handling it in the RTOS idle hook
Correct answer: A. A high-priority timer interrupt with bounded, deterministic execution reliably meets a tight hard-real-time deadline.
In a CAN bus network, a node's transmitted dominant bit is overwritten during arbitration. What does the CAN protocol do?
- A. It raises a bus-off error immediately
- B. The node loses arbitration and switches to receive, retrying later without corrupting the winning frame ✓
- C. Both frames are discarded
- D. The bus resets
Correct answer: B. CAN's non-destructive bitwise arbitration lets the lower-priority node back off and retransmit while the higher-priority frame proceeds intact.
A firmware image runs correctly from the debugger but fails on cold boot from flash. Which startup issue is the most likely culprit?
- A. Missing or incorrect data (.data) copy and .bss zeroing in the reset handler / startup code ✓
- B. Too many volatile variables
- C. Incorrect UART baud rate
- D. The optimizer level is too low
Correct answer: A. The debugger may pre-initialize RAM, masking a startup that fails to copy .data from flash or zero .bss on a real cold boot.
You need to detect single-bit corruption in a critical config block stored in EEPROM. Which is the most appropriate lightweight integrity mechanism?
- A. Store the data twice with no check
- B. Append a CRC (e.g., CRC-16/CRC-32) and verify it on read ✓
- C. Encrypt with AES only
- D. Use a longer variable name
Correct answer: B. A CRC reliably detects bit errors in stored data at low computational cost, unlike encryption which provides confidentiality, not integrity checking.
An ADC reading is noisy at exactly the PWM frequency driving a nearby motor. Beyond software filtering, which hardware-aware fix best addresses the root cause?
- A. Increase the MCU clock
- B. Improve PCB layout/grounding and synchronize ADC sampling away from PWM switching edges ✓
- C. Use a larger stack
- D. Switch from C to assembly
Correct answer: B. The noise is switching-induced coupling; better grounding/layout and sampling away from PWM edges attacks the source rather than masking it.