Interview questions · free
Embedded Software Engineer interview questions and answers
27 questions Embedded Software Engineer interviews in India ask, grouped by the 6 skills they test, with a short model answer for each. Then the HR round every job has. Try each one out loud before you open the answer.
- 27 questions
- 6 skills
- 16 for freshers
- Updated 30 Oct 2026
First mock interview free: 3 questions, a score and feedback on each · No card needed
Answer out loud first. Read the question, say your answer as you would in the room, then open the model answer and compare. Interviewers ask follow-ups, so learn the reasoning, not the words.
Embedded C · Core skill
C language
Embedded firmware is still written mostly in C, and interviewers probe the parts that matter on small chips: exact sizes, bits, storage classes and how structs sit in memory.
How do you set, clear, toggle and check bit n of a register in C?Fresher
Use a mask with only bit n set, (1U << n), and the bitwise operators. Set: reg |= (1U << n). Clear: reg &= ~(1U << n). Toggle: reg ^= (1U << n). Check: if (reg & (1U << n)), or ((reg >> n) & 1U) to get 0 or 1.
Use an unsigned constant, 1U, because shifting a signed 1 into the top bit of an int is undefined behaviour. For hardware registers, remember that set and clear are read-modify-write operations: if an interrupt changes the same register in between, one change can be lost, which is why many microcontrollers offer separate set and reset registers that change bits in one write.
What does the static keyword mean in C? Explain its different uses.Fresher
static means different things in two places. Inside a function, a static local variable is created once and keeps its value between calls, because it lives in the data or BSS section rather than on the stack; for example, a counter of how many times a function ran. It's initialised only once, to zero if you don't give a value.
At file level, static on a global variable or a function gives it internal linkage: it's visible only inside that .c file. That's the C way to keep a module's internals private and avoid name clashes between files. In embedded code, a static buffer is also a common way to avoid putting a large array on a small stack.
What is the difference between a structure and a union? Where would you use a union in embedded code?Fresher
In a structure every member has its own memory, so its size is at least the sum of its members, plus any padding. In a union all members share the same memory, so its size is that of the largest member, and writing one member overwrites the others.
In embedded code a union is used to view the same bytes in two ways, for example a 32-bit value and its four bytes when building a communication frame, or a register as a whole word and as named bit-fields. Mention the catches: the byte order you see depends on the processor's endianness, and bit-field layout is compiler-dependent, so code like this isn't portable between compilers and chips.
What is sizeof(struct { char a; int b; char c; }) on a 32-bit microcontroller, and why? How would you reduce it?1-6 years
Usually 12, not 6. The compiler aligns a 4-byte int on a 4-byte boundary, so it adds 3 padding bytes after a, then b takes 4 bytes, c takes 1, and 3 more padding bytes follow so that in an array every element's int is aligned again. Reordering the members from largest to smallest, int b first and then the two chars, gives 8 bytes.
Packing the struct with __attribute__((packed)) or #pragma pack removes padding, but unaligned accesses are slower, and on some cores, such as Cortex-M0, they cause a fault. For data sent over UART or CAN, don't send a struct's raw bytes; write each field into a byte buffer explicitly, which also fixes endianness. Use stdint.h types like uint32_t for exact sizes.
Embedded C · Core skill
Pointers and memory
Pointers are the most tested topic in embedded interviews in India, because firmware reaches hardware registers, buffers and callbacks through them, and pointer bugs crash devices in the field.
What is the difference between const int *p, int *const p and const int *const p?Fresher
Read the declaration from right to left. const int *p is a pointer to a constant int: you can move p to point elsewhere, but you can't change the value through it, so *p = 5 is an error. int *const p is a constant pointer to an int: it always points to the same place, but you can change the value there. const int *const p is both: neither the pointer nor the value can be changed through it.
In embedded code, a function that only reads a buffer takes const uint8_t *buf, which documents the promise and lets the compiler check it. A hardware register at a fixed address is often written as a constant pointer to volatile data.
If int *p holds the address 0x1000 and an int is 4 bytes, what is p + 1? Why would you use a pointer to a pointer?Fresher
p + 1 is 0x1004, not 0x1001. Pointer arithmetic moves in units of the pointed-to type, so adding 1 moves by sizeof(int). For a char pointer it would be 0x1001, and for a pointer to a 12-byte struct, 0x100C. That's why p[i] and *(p + i) are the same thing.
A pointer to a pointer is needed when a function must change the caller's pointer itself, not just the data it points to. For example, inserting at the head of a linked list: the caller passes &head, so push receives a pointer to the head pointer, creates a node and stores the new node's address through it, and the caller's head is updated. An array of strings, char *argv[], is also a pointer to pointers when passed to a function.
What are dangling pointers, wild pointers and memory leaks?Fresher
A dangling pointer points to memory that is no longer valid: memory that was freed, or a local variable of a function that has returned. Using it may seem to work, then corrupt data later. A wild pointer is one that was never initialised, so it holds a random address. A memory leak is allocated memory that is never freed, often because the only pointer to it was overwritten or went out of scope.
The habits that prevent them: initialise pointers to NULL, set them to NULL after free, never return the address of a local variable, and pair every allocation with a clear owner who frees it. On a device that runs for months, even a small leak eventually exhausts the heap.
Why do many embedded projects avoid malloc and free? What do you use instead?1-6 years
Three reasons. Fragmentation: after many allocations and frees of different sizes, a small heap can have enough free memory in total but no single block large enough, so an allocation fails after days of running. Timing: malloc's execution time isn't predictable, which is a problem for real-time code and interrupts. And failure handling: there's often no sensible recovery when allocation fails in a device. Safety standards such as MISRA C forbid the standard heap functions.
Instead, allocate statically at compile time, so the linker map shows the exact memory use, or allocate once at start-up and never free. Where dynamic objects are needed, use fixed-size memory pools, which can't fragment, or the RTOS's own allocation scheme, and check stack sizes as well.
What is a function pointer? Show how you'd declare one and give a real embedded use.1-6 years
A function pointer holds the address of a function, so you can choose at runtime which function to call. Declaration: void (*handler)(uint8_t event); assign it with handler = led_on; and call it with handler(5). A typedef makes it readable: typedef void (*callback_t)(uint8_t);
Embedded uses are everywhere. The interrupt vector table is an array of function pointers. A driver lets the application register a callback, such as a function to call when a UART frame arrives. A state machine can be a table of function pointers indexed by state, which replaces a long switch. Always check a function pointer isn't NULL before calling it: jumping to address zero or garbage usually ends in a hard fault.
Microcontrollers · Core skill
Peripherals (GPIO, timers, ADC)
The job is making hardware do things, so interviewers ask how you drive pins, timers and ADCs from the datasheet, often at register level rather than only through a vendor library.
How would you configure a GPIO pin to blink an LED and read a push button on a microcontroller such as an STM32?Fresher
First enable the clock for the GPIO port in the reset and clock control (RCC) registers; a peripheral without a clock ignores writes. For the LED, set the pin's mode to output, usually push-pull, and toggle it through the output data register, or better the bit set/reset register, which changes a pin in one write without affecting the others. Add a delay or, better, a timer for the blink rate.
For the button, set the pin as input with an internal pull-up or pull-down so it doesn't float, and read the input data register. Mechanical buttons bounce for a few milliseconds, so debounce in software, for example by accepting a change only after it is stable for 20 ms.
What is PWM? How would you generate a 1 kHz PWM signal at 25% duty cycle with a timer running from a 72 MHz clock?Fresher
PWM switches an output on and off at a fixed frequency, and the fraction of time it's on, the duty cycle, sets the average power: LED brightness, motor speed or a servo position. A timer counts up to its auto-reload value and restarts; the output is high until the count reaches the compare value.
On an STM32-style timer, PWM frequency = timer clock / ((PSC + 1) × (ARR + 1)). Set the prescaler PSC = 71, so the timer ticks at 72 MHz / 72 = 1 MHz. Then ARR = 999 gives 1 MHz / 1000 = 1 kHz. For 25% duty, set the compare register CCR = 250, since duty = CCR / (ARR + 1). A larger ARR gives finer duty steps.
A 12-bit ADC with a 3.3 V reference reads a sensor, but the values jump around. How do you convert the reading to volts, and how do you make it stable?1-6 years
The voltage is roughly raw × 3.3 / 4095, since a 12-bit ADC gives 0 to 4095; some datasheets use 4096, a one-count difference. So a reading of 2048 is about 1.65 V, and one count is about 0.8 mV, which is why small noise shows up.
To stabilise it: check the reference voltage is clean, since any ripple on it scales every reading; increase the sampling time if the sensor has a high source impedance, or add a buffer; add an RC filter at the pin; keep the analog trace away from switching signals and use a proper analog ground. In software, average several samples or use a moving average, and calibrate against a known voltage. Sample at least twice as fast as the fastest change you need.
You have to bring up a peripheral on a new microcontroller you haven't used before. How do you go about it?1-6 years
I start with the reference manual's chapter for that peripheral and the datasheet for the pins: which pins can carry it, alternate function numbers, voltage levels and timing. I also read the errata sheet, because silicon bugs in that peripheral can waste days. Then I list the steps in order: enable its clock, configure the pins and their alternate functions, set the peripheral's registers, enable interrupts in the peripheral and in the interrupt controller.
I often start from the vendor's example or HAL to get something working, then check the registers in the debugger against what I expected. Finally I verify on the hardware with an oscilloscope or logic analyser: the right frequency, levels and timing, not just that the code runs.
Microcontrollers
Interrupts
Firmware reacts to the outside world through interrupts, and many field bugs are interrupt bugs, so interviewers check that you write short, safe ISRs and share data correctly.
What is an interrupt service routine? What should you do, and avoid, inside one?Fresher
An ISR is a function the processor runs automatically when an interrupt occurs, such as a timer overflow, a received UART byte or a pin change. The processor saves its context, runs the ISR and returns to where it was.
Keep ISRs short. Do the minimum: clear the interrupt flag if the hardware needs it, read the data, store it in a buffer or set a flag, and let the main loop or a task do the rest. Avoid long loops, delays, printf, malloc and blocking calls like waiting on a mutex, because they delay every other interrupt and can deadlock. If the flag isn't cleared, the ISR keeps firing again and the main code never runs.
Why do you declare a variable shared between an ISR and the main loop as volatile? Is volatile enough?Fresher
volatile tells the compiler the variable can change outside the normal flow of the code, so it must read it from memory every time. Without it, in a loop like while (!data_ready) {}, the optimiser may read data_ready once, keep it in a register and loop forever, even after the ISR sets it. The same applies to hardware registers.
But volatile isn't enough on its own: it doesn't make access atomic. Reading a 32-bit counter on an 8-bit microcontroller takes several instructions, and an interrupt in the middle gives a half-updated value. Incrementing a shared variable is read-modify-write, too. Protect such accesses by briefly disabling that interrupt, or use atomic operations or a lock-free ring buffer with one writer and one reader.
Explain interrupt priorities and nesting on a Cortex-M microcontroller. What affects interrupt latency, and how would you measure it?1-6 years
The NVIC gives each interrupt a priority, where a lower number means higher priority. The priority is split into a pre-emption part, which decides whether one interrupt can interrupt another running ISR (nesting), and a sub-priority, which only decides the order among pending ones. Cortex-M also tail-chains: if another interrupt is pending when an ISR ends, it runs without restoring and saving the context again.
Latency grows when a higher-priority ISR runs long, when code disables interrupts for long critical sections, and with flash wait states. To measure it, toggle a spare GPIO at the start of the ISR and compare it with the triggering signal on an oscilloscope or logic analyser. That shows the worst case under load, not just the average.
Reading an answer isn't the same as giving one
In a mock interview you answer new Embedded Software Engineer questions out loud or typed, and every answer is scored, with what to fix and a stronger answer.
RTOS
RTOS concepts
Larger firmware in automotive, industrial and IoT products runs on an RTOS such as FreeRTOS, so interviewers check that you can split work into tasks and share data without races.
What is the difference between a mutex and a binary semaphore?Fresher
Both can be taken and given, but they're meant for different jobs. A mutex protects a shared resource, such as a UART or an I2C bus, so only one task uses it at a time. It has an owner: only the task that took it should give it back, and in FreeRTOS it has priority inheritance to limit priority inversion. It must not be used from an ISR.
A binary semaphore is for signalling: one side gives it, another waits for it. The classic use is an ISR giving a semaphore with xSemaphoreGiveFromISR to wake a task that processes the data. It has no owner and no priority inheritance, so using it as a lock can cause priority inversion problems.
What is priority inversion? How do you prevent it?1-6 years
Priority inversion happens when a high-priority task waits for a resource held by a low-priority task, and a medium-priority task, which doesn't need the resource, pre-empts the low-priority one. The high-priority task is then effectively blocked by the medium one, possibly for a long time, and can miss its deadline. The well-known case is NASA's Mars Pathfinder, which kept resetting until priority inheritance was enabled on a mutex.
Prevention: use a mutex with priority inheritance, which temporarily raises the holder to the waiting task's priority, or a priority ceiling protocol. Also keep critical sections short, and avoid sharing resources between tasks of very different priorities where you can.
Data arrives on a UART at a high rate, and you need to parse it and log it to flash. How would you structure this with an RTOS?1-6 years
Keep the interrupt fast and move the work into tasks. The UART ISR, or better a DMA transfer with an idle-line interrupt, puts bytes into a queue or stream buffer and wakes a parser task with a FromISR call. The parser task, at a fairly high priority, assembles and checks frames and sends complete messages through a second queue to a lower-priority logging task, because flash writes are slow and may block.
Size the queues for the worst burst, and decide what happens when one fills: drop and count, never block in the ISR. Check each task's stack with the high-water mark functions, and use a watchdog that's fed only when all tasks are known to be running.
Debugging
Hardware debugging tools
When firmware fails on a board, the bug may be in code or hardware, so interviewers want to know you can use a debugger, oscilloscope and logic analyser to find out which.
What is the difference between JTAG and SWD?Fresher
Both connect a debug probe, such as an ST-LINK or a J-Link, to a chip to program flash, set breakpoints, step through code and read memory and registers. JTAG is an industry standard (IEEE 1149.1) that uses four or five signals: TCK, TMS, TDI, TDO and an optional TRST. It also supports boundary scan for testing board connections, and several chips can be daisy-chained on one JTAG chain.
SWD is ARM's two-wire alternative, SWDIO and SWCLK, offering the same debugging on Cortex-M chips with fewer pins, which matters on small packages. An extra SWO pin can stream trace output, such as printf-style messages, without using a UART.
When would you use an oscilloscope, and when a logic analyser?Fresher
An oscilloscope shows the real analog waveform on a few channels: voltage levels, rise times, ringing, noise and glitches. A logic analyser captures many digital channels, often 8 or 16, as just high or low, over long periods, and decodes protocols such as UART, SPI and I2C into bytes.
They often work together. If an I2C sensor doesn't respond, the logic analyser shows which address was sent and whether the sensor acknowledged it. If the decode looks garbled, the oscilloscope may show slow, rounded edges because the pull-up resistors are too weak for the bus speed. So use the analyser for what was sent, and the scope for whether the signal is electrically good.
Your firmware on a Cortex-M board suddenly lands in the HardFault handler. How do you find the cause?1-6 years
Find the instruction that faulted. On entry the processor stacks registers, including the PC of the faulting instruction and LR, so in the debugger or a fault handler I read the stacked PC and look it up in the disassembly or map file, or with addr2line. Then I read the fault status registers, such as CFSR and HFSR, and the fault address registers, which say whether it was a bad memory access, an unaligned access, an undefined instruction or a divide by zero.
The usual causes are a NULL or dangling pointer, a stack overflow overwriting data, an uninitialised function pointer, or a buffer overrun. A stack overflow is likely if the fault moves around as code changes; fill stacks with a pattern and check how much is used.
Every job
HR and behavioural round
Embedded teams work closely with hardware engineers and follow strict processes, so the HR round checks your hands-on project work, patience with debugging and fit for that way of working.
Tell me about yourself.Fresher
Keep it to about a minute and lead with hands-on embedded work. For example: "I'm a [ECE / EEE] graduate from [college]. I got interested in embedded systems through [club or course], and my main project was [project], built on [STM32 / ESP32 / 8051], where I wrote the drivers for [sensor or peripheral] in C, without relying only on Arduino libraries. I debugged it with [oscilloscope / logic analyser]. I also did [internship or certification]. I'm looking for a role where I can write firmware for real products and learn from experienced engineers."
Be ready to draw your project's block diagram on a whiteboard.
Why do you want to work in embedded software rather than web or application development?Fresher
Show a real interest in hardware, with evidence. For example: "I enjoy seeing code make something physical happen, like a motor turning or a sensor reading. In my [project], getting [peripheral] working from the datasheet took days, but solving it taught me more than any app I built. I like that embedded work needs both electronics and programming, and that the products, such as [automotive, medical or industrial devices], have to be reliable."
Avoid answers that suggest you'll leave for an IT job at the first chance; interviewers for core roles worry about that.
Our projects follow coding standards, code reviews and detailed documentation. How do you feel about working that way?Fresher
Say you value it and explain why it matters in embedded work. For example: "I think it's necessary. Firmware goes into devices that can't easily be updated, and in fields like automotive or medical a bug can be dangerous. I've read about MISRA C, and in my project I [used a static analysis tool / had my code reviewed by a teammate], which caught [a real issue]. I'd rather have my code reviewed and learn than have a bug found in the field."
Interviewers want to hear that you see process as protection for the product, not as paperwork.
Tell me about the hardest bug you've fixed in firmware.1-6 years
Use STAR and show your method, not luck. "Our device reset randomly once or twice a day in the field (situation). I was asked to find it (task). I added a reset-cause log at start-up and found watchdog resets, then saved the stacked PC on faults, which pointed to a stack overflow in the communication task when a long frame arrived. I confirmed it by filling the stack with a pattern and checking the high-water mark (action). Increasing the stack and bounding the frame length fixed it, and we added stack checks to our test plan (result)."
Mention the tools you used and what you'd now do earlier.
You're not sure whether a problem is in the hardware or in your firmware. How do you work with the hardware team on it?1-6 years
Show that you bring evidence, not blame. Narrow it down first: does it happen on several boards or one, with a known-good firmware, and what does the scope show at the pins? Then share what you found clearly. For example: "The SPI flash sometimes returned wrong data. I captured the signals and saw ringing on the clock line at 20 MHz. I showed the hardware engineer the capture; we reduced the clock to 10 MHz as a workaround, and they added a series resistor in the next board revision."
Interviewers want someone who collaborates, documents the finding and owns the firmware side.
Free interview questions, roadmaps and mock interviews: https://myskillgrid.com/interview-questions/embedded-software-engineer/
Ready to answer them for real?
Your first Embedded Software Engineer mock interview is free: 3 questions, a score and feedback for each, and a stronger answer to learn from, in about 10 minutes.