Interview Prep & Tips /Embedded Systems
Embedded C essentials
Sample guide. Edit or replace it with your own material.
1. What does volatile do, and when do you need it?
- It tells the compiler that the value can change outside the normal program flow, so every access must actually read or write memory. The compiler can’t cache the value in a register or remove the access.
- Use it for: memory-mapped peripheral registers, variables shared between an ISR and main code, and memory changed by DMA.
- It does not provide atomicity or ordering between CPU cores. Use critical sections, atomics, or barriers for that.
- Follow-up question: what does
const volatilemean? It is a read-only register whose value hardware can still change, such as a status register.
2. Where do variables live?
| Section | Contents | Location at runtime |
|---|---|---|
.text |
Code and constants (often .rodata too) |
Flash |
.data |
Initialised globals and statics | RAM, with initial values copied from flash at startup |
.bss |
Zero-initialised or uninitialised globals and statics | RAM, zeroed at startup |
| Stack | Local variables, return addresses | RAM |
| Heap | malloc allocations (often avoided in embedded) |
RAM |
3. The meanings of static
- On a local variable: it keeps its value between calls and lives in
.data/.bss, not on the stack. - On a global variable or function: it has internal linkage and is visible only in that file.
4. Rules for writing ISRs
- Keep them short: set a flag or push to a buffer, and do the work in the main loop.
- Don’t block or call non-reentrant functions (such as
printf). - Mark shared variables
volatileand protect multi-byte accesses. - Clear the interrupt source, or it will fire again immediately.
5. Integer promotion trap
uint8_t a = 0xFF;
if (~a == 0x00) {
/* Never reached */
}
a is promoted to int before ~ is applied, so ~a is 0xFFFFFF00
(on a 32-bit int), not 0x00. The fix is (uint8_t)~a == 0x00.
Practice
- Write
SET_BIT,CLEAR_BIT, andTOGGLE_BITmacros, and explain why the arguments need parentheses. - Explain why
sizeof(struct { char c; int i; })is usually 8, not 5.