200 Embedded and IoT Software Engineering Interview Questions – Part 3 Microcontrollers

So far in part-1 of this interview questions series, we saw about

  • Questions about yourself
  • Questions about the projects you have done and
  • Questions from C programming language

Then in part-2, we saw some questions about the Basics of electronics.

You can find parts 1 and 2 in the links below.

200 Embedded and IoT Software Engineering Interview Questions – Part 1

200 Embedded and IoT Software Engineering Interview Questions – Part 2 Basics of Electronics

Now lets head onto the next part and in this part, we will look at some questions about microcontrollers. Microcontroller is the most important topic in embedded systems, so it is important that you have a good grasp on the concepts related to it.

As usual, I have divided the questions into 3 categories of easy medium and hard. So let’s begin!

Difficulty level: Easy

Question #1: List 4 types of timers and explain where to use them

Answer #1:

  • General-purpose timers
  • Watchdog timers
  • SysTick timers
  • Real-time clocks

You can read more about them in this article

Question #2: List 3 serial communication protocols commonly used in embedded systems for onboard communication and explain when to use which one.

Answer #2: 

UART, SPI, and I2C are the most common types of communication protocols. Out of these 

  • UART can do full-duplex communication between 2 devices using just 2 wires (RX and TX)
  • SPI can also do full-duplex communication between one master and multiple slaves using 4 wires 
    • Master-In Slave-Out (MISO) wire, 
    • Master-Out Slave-In (MOSI) wire 
    • Slave Select (SS) wire and 
    • Serial Clock (SCK) wire 
  • I2C can only do half-duplex communication between one master and multiple slaves using just 2 wires 

UART is to be used when 

  • there is a clock source on both sides that are communicating as this is an asynchronous form of communication. 
  • The communication channel is full-duplex, meaning both sides can talk and hear at the same time.

SPI is used when 

  • Only one side has a clock source
  • A number of slaves (eg, sensors) need to talk to one master (microcontroller) through the same wires
  • Full duplex communication is needed

I2C can be used when 

  • There is a single master multiple slave configuration (same as SPI)
  • there is a lack of available pins to use (SPI uses 4 pins, I2C uses only 2) 
  • Speed is not important as I2C is very slow compared to SPI

Question #3: Explain interrupt and polling

Answer #3: 

If our application is waiting for an event to occur, it can do it 2 ways.

  • Interrupts and
  • Polling

Polling

This is basically looping to see if an event has occurred or not. It is a waste of CPU time as the entire execution will be stuck here waiting for an event.

Interrupts

In simple terms, these are asynchronous mechanisms where a hardware event can be used to call a function called the Interrupt Service Routine which handles that particular event. 

Here the CPU need not wait at one spot, rather it can go on to do its other tasks and once the hardware event occurs, the CPU will be notified of it and it can take necessary action.

You can read more about it in section 8 of this article where I have explained this concept in more detail using examples.

Question #4: What is an ISR?

Answer #4: ISR stands for Interrupt Service Routine. It is just a C function that gets executed once a particular interrupt occurs.  Each of the registered interrupts will have its own C function/ISR to handle the event.

Question #5: What is an interrupt vector table?

Answer #5:

The interrupt vector table is simply a table with 2 columns, column1 contains the interrupt number (IRQ number) and column2 contains the address of the function to be executed (ISR) if a given interrupt occurs. 

Interrupt Vector Table
Interrupt Vector Table

Question #6: What is the difference between an SRAM and DRAM?

Answer #6: 

SRAMDRAM
Construction PrincipleIt uses a cross-coupled flip flop configuration of transistorsIt uses a capacitor transistor circuit to hold data
CostRelatively more expensive, it needs more transistors per bit of data it can storeRelatively less expensive, as fewer transistors per bit of storage are needed
Speed4X more than DRAM4X less speed
VolatilityAs long as power is ON, it can store data since it uses no capacitorsData needs to be continuously refreshed (usually in the order of 4 times a second) since the capacitors leak power.
Power consumptionLessMore
Addition components neededNoneDRAM controllers are needed to make it work like an SRAM. This controller offloads the data refreshing duties of a microprocessor and hence a DRAM coupled with a DRAM controller behaves more like an SRAM from the processor’s perspective.
Application areasApplications/scenarios that need very fast memoryBudget applications that do not need the speed of SRAMs

Question #7: Explain the use of Masked ROMs

Answer #7:

The main characteristic of this device is the fact that the data is written onto the device as it gets manufactured and it is impossible to change them. This is done by designing the chip in such a manner so that it already contains the necessary data. 

Function and Application areas

They usually serve the function of storing the bootloaders in microcontrollers and to store microcode on microprocessors. This type of storage is generally used in mass-produced, long term devices where each penny counts. The IC area per bit for masked ROMs is generally lower compared to other types and hence they are favored by manufacturers.  Also since the area occupied is smaller, the overall device/chip’s size is also reduced. Examples include the processors and microcontrollers that we use in our projects which are usually produced in huge numbers and they are produced usually decades

Question #8: Describe the C-Runtime Environment on microcontrollers

Answer #8:

The code written in C needs a particular environment to execute.

This environment mainly has the following

  • a stack to hold the local variables
  • a heap to be used for dynamic memory allocation.

Usually, manufacturers provide the code to set up this environment in a file named startup.c or crt.s (stands for C-runtime).

This code usually does the following

  • allocates space for the stack
  • initializes the stack pointer
  • allocates space for the heap
  • copies the initialized global/extern and static variables from .bss area of the RAM
  • makes uninitialized global/extern and static variables into their default values (usually zeros).

After it does all of the above actions, it calls main and starts executing the application that us embedded software engineers wrote.

Once the main returns, the code either goes into an infinite loop or halts the processor as designed by us.

Question #9: Explain 2 types of addressing spaces on embedded systems

Answer #9:

There are 2 address spaces in embedded systems namely

  • Memory space and
  • I/O space

Memory space is as the name describes exclusively for memory like RAM and ROM. Here the code and data are stored and accessed whenever needed.

The I/O space is for the peripherals like GPIO, UART, SPI etc., This part acts differently as it is not just storage and retrievals, rather the data being sent here has an action associated with them. For example, if you write to the GPIO output registers, it will change the output of the GPIO pins.

If the peripherals are mapped into the memory space they are called Memory Mapped I/O as from a programming point of view, it is just another memory location but actually mapped to the peripherals’ registers. This makes it easier for both the hardware and software designers and as no special routine is needed to access the I/O space anymore and hence it is more preferred.

Question #10: Describe JTAG

Answer #10: JTAG stands for Joint Test Action Group. It is a standard originally developed to help in PCB manufacturing and board assembly. JTAG introduced a standardized way to do automated testing of assembled boards using a technique called boundary scanning testing. 

JTAG also lets us program the firmware onto the flash memory on board and it helps in debugging during development.

Difficulty level: Medium

Question #1: Difference between CISC and RISC architectures

Answer #1:

CISC stands for Complex Instruction Set Computer and RISC stands for Reduced Instruction Set Computer

The CISC computers have bigger computing power, as they can calculate complex mathematical computations using a single instruction but to do that they need complex hardware. Examples include Intel and AMD’s desktop and laptop processors.

RISC computers, on the other hand, handle complex computations by breaking them down into simpler parts as they do not have the complex circuitry to handle the computation. But since the circuits are simpler, they generally have lesser power consumption and are usually preferred for battery-powered devices. Examples can include ARM processors used in embedded systems and smartphones.

Question #2: Explain the use of DMA 

Answer #2: DMA stands for Direct Memory Access. It is a peripheral found commonly in modern microcontrollers. Their function is to offload the data move operations from the processor so that the efficiency and performance of the system can be improved.

You can read more about DMA in section 9 of this article

Question #3:  In what scenario is interrupt better than polling?

Answer #3: Interrupt is better if we care about the power consumption of the system as CPU polling consumes a lot of power. 

Question #4:  In what scenario is polling better than interrupt?

Answer #4: Polling is better if we care about the time duration taken to respond to an event. 

Polling is a better option because there is no context switching taking place here. Usually when an interrupt occurs, the CPU stops executing whatever code its is going through and stores all the local variables and registers like Program counter on the stack, then it starts executing the ISR. When the ISR returns, the CPU has to go back to the previous state by taking all the data back and loading its registers. This process takes time and introduces an overhead. Hence if an event is happening with a very short durations in-between 2 given occurrences, and we don’t care about the power consumption, then polling is a better option.

Question #5: How to make a software timer?

Answer #5: 

Software timers are usually built on top of Hardware General Purpose timers operating in a periodic mode where once the loaded time expires it reloads the initial value and starts counting down again.

So every time the timer runs out, it produces an interrupt. On the ISR we can increment a variable every time this interrupt occurs and this will produce the necessary software timer tick. 

For example, say we need a granularity of 1ms, then we set the hardware timer to a period of one millisecond and make a simple ISR as follows

int64_t timer_ticks_ms;

void timer_ISR()
{
    timer_ticks_ms++;	
}

Then say, a situation demands us to wait for 10ms, we can create a software timer as follows

void software_timer_start()
{
	static int starting_tick = timer_ticks_ms;
	****
}
****

Question #6: Explain Maskable and Non-Maskable interrupts

Answer #6:

Maskable interrupts, as the name says, can be “masked”. In other words, they can be ignored by the processor. For example, GPIO pins have the ability to interrupt the CPU, but they must be registered to the Nested Vectored Interrupt Controller a.k.a NVIC (a peripheral typically found in all modern microcontrollers) for the CPU to be able to see that an interrupt has come in.  If it is not registered the CPU will simply ignore it and run as if the interrupt never occurred.

Non-Maskable interrupts, on the other hand, are by default enabled, and us programmers have no say in the decision of whether the CPU must process it or not. Usually, errors like stack-overflow errors are non-maskable, so that they cannot be caught by the CPU as it has the potential to corrupt the other memory regions if left unhandled. These interrupts are usually errors and are referred to by the term Hard-faults

Question #7: Explain Synchronous and Asynchronous communication

Answer #7: Synchronous transmission is usually done with the help of a clock signal. Examples include SPI and I2C. Here the data is transmitted /read by the receiver using the clock signal. For example, every time the clock signal goes from low to high, a bit is transmitted on the data line. 

Say the first bit is one, then the pin is held high for that particular clock period and if the next bit is Zero then once the clock signal turns from low to high in the next period, the pin voltage is made the ground voltage.

The pin in the receiving end reads these bits say in the middle of the clock pulse when the clock pulse goes from 1 to 0, and thus data transmission occurs.

Let’s take an example to send a value 0xCB which in binary is 11001011 and see how this data is transmitted.

Clock signal vs Data signal
Clock signal vs Data signal

As you can see in the above picture, the data is transmitted on the rising edge of the clock signal. The receiver can choose to read this data on the falling edge of the clock signal since the data will not change at this point and the receiver can have half clock cycle to read this data in.

Asynchronous communication, on the other hand, does not use a single clock source for the transmission. A famous example for this one is UART which stands for Universal Asynchronous Transmitter Receiver. 

If you have ever used UART, then you would have noticed that we need to set some parameters like the baud rate, data bits, stop bits and parity before we start the communication. The page for setting them up in the PuTTY app is shown below

Putty Serial Port Configuration
Putty Serial Port Configuration

Here instead of using a common clock signal, the 2 parties communicating agrees on a clock rate (baud rate in UART) beforehand so that they can talk to each other under the assumption that the other side is sending/receiving at the agreed clock rate. 

If you wish to experience what I am talking about, first make sure everything is running correctly and end the session and open it again, but this time change the baud-rate and then start the communication again. I bet you will get some gibberish on the screen instead of the data you were expecting! This is because the 2 applications have pre-agreed on one baud-rate and you have used some other baud rate and this causes the data to be read at the wrong times resulting in the gibberish. 

In the pic below the baud-rate is correctly set (115200 for this case) and the app is able to take in the data and transform it from ASCII to text and correctly display it to us.

Now let’s change the baud-rate to 9600 and see what happens

As you can see some gibberish is printed. This is because the agreed baud rate was 115200 bytes per second but the receiving side is reading at 9600 bytes per second and this causes the data on the receiving side to be corrupted and we are seeing some gibberish on the screen!

Question #8: Explain Half and Full-duplex communication

Answer #8:

In half-duplex communication, only one side can talk at a time. Walkie Talkies are good examples here. When one side is talking the other side needs to listen. Example of embedded half-duplex communication is I2C.

In full-duplex communications, there are separate lines for sending and receiving and hence both the parties communicating can talk at the same time.

Question #9: Given a 10mAH battery at 5V connected to a circuit that consumes 5mW. How long is the battery going to last?

Answer #9:

Since the voltage is 5V and the power consumption is 5mW then the current it consumes can be calculated as

Current = Power/Voltage = 5mW/5V = 1mA

The battery has a total of 10mAH so it can provide power to the circuit at 1mA for 10 hours.

Question #10: What is an NVRAM?

Answer #10: 

NVRAM stands for Non-Volatile RAM which is basically an SRAM with a battery so that it can hold the data in it. It is the fastest available secondary memory and used on applications that need really short loading times. 

Difficulty level: Hard

Question #1: How to reduce the context switching time?

Answer #1:
During the context switching time, the following activities happen.

First, the microcontroller stores the present state of the system by doing the following.

  • The value in program counter is stored in the stack so that the processor knows where to return to once the function exits.
  • The value of the stack pointer is also stored
  • The local variables that are presently placed in the processor’s registers are then stored onto the stack
  • All the flags are also stored in the stack so that they can be retrieved later and copied back to the registers

Then on the function side, the parameters that were passed to it will be copied onto the stack and function will start executing.

Once all these values are stored, the function that was called will be executed.

To reduce the time duration it takes to save the present state of the microprocessor there is nothing much that can be done as these are all important values and nothing can be skipped. Only one thing that can be done here is to make the functions inline if they are short enough and are not called too many times. If it is made inline then the compiler just copies the function’s code and pastes them where ever the function call takes place. On one side this increases code size, but on the other side, it reduces/eliminates the context switching time.

But on the function side, the size of the parameters being passed can be optimized to reduce the copying time. This can be done in 2 ways

  1. Sending pointers instead of the entire function in case the parameter size is large
  2. If the variable is being passed to many functions, then instead of keeping them local they can be made global instead so that the copying parameters process can be skipped.

These are the ways to reduce the context switching times.

Question #2: Consider a microcontroller with 1000kB of flash and 1kB of EEPROM memory, what would you use the 2 memories for?

Answer #2: 

Flash memory is used for storing the executable binary which is compiled from the source code and the EEPROM can be used for storing the run-time constants. To understand what I mean by run-time constant, have a look at the example below.

For example, say we have a device that measures the temperature and displays it on an LCD screen. Say he has the option to show the temperature in either Celsius or Fahrenheit. This preference needs to be stored onto EEPROM so that if the user changes the battery, our program can still read this off the EEPROM and use it to set the correct unit for the temperature. 

Question #3: How to minimize wear on flash-based memory chips?

Answer #3: 
The Flash Chips usually have a limited write cycle endurance, usually in the order of 100,000 times. As a device driver writer, it is our duty to make sure that the flash wears evenly to prolong its life-span.

Assume we have a 100MB flash device, and our application usually writes about 40MB of data each time it runs. Now if we only write the values to the first 40MB of the flash device, that particular portion of memory is going to wear out first and the remaining 60MB of the memory will never be used.

So instead we have to make sure that the total 100MB is utilized, we can do this by writing in the 0-40MB space for the first time, 40-80MB range the second time and 80-100, 0-20MB in the 3rd time and so on by cycling the portions of the flash memory we are using. In the code, we just need to make sure that we know where we need to start writing from. Thus we can make the chip last 2.5 times more compared to just writing in the first 40MB and hence we are leveling the wear and tear of the flash chips.

Question #4: What is a bootloader? 

Answer #4: An embedded bootloader is a piece of software that takes a system from a power-up state to a usable state. To be more specific, it is the code that runs from the moment you press the power button, till the point in time where it reaches the main function in your code.

Question #5: How to get into bootloader mode?

Answer #5: It depends on the specific device you are using, so you need to go look at the datasheets and user guides of a specific device. But in general, either a particular memory location value or the state of a given GPIO pin is used to enter the bootloader mode

If you are unfamiliar with bootloaders I suggest you take a look at this article

Question #6: What is the reset vector?

Answer #6: 
This is the address on the memory, the microprocessor will execute first as soon as it comes out of a reset, like powering on the device.

Usually, a JUMP instruction is placed here to forward the execution to the hardware initialization instructions in the memory.

Question #7: Expand and explain OTA updates

Answer #7: 

OTA stands for, Over The Air, it’s a method of updating a device after it has reached the end-user using some wireless communication standard like WiFi or Bluetooth.

Question #8: What are hard-faults?

Answer #8: 
These are runtime errors that the system can only recover from through a reset of the system. If your program does something that it is not supposed to do, then the system goes into a hard fault routine, which is similar to an ISR, but it never returns as the system is unable to continue execution.

For example, say our program is accessing a protected memory region, because of a stack overflow bug, then the system cannot continue as it does not know where to keep the next local variable as there is no more space on the stack. Then it halts the operations and goes into the hard-fault routine.

Question #9: Explain the different sections of the final linked executable binary

Answer #9: They include 

  • .text: the code to be executed
  • .data: initialized extern and static variables
  • .bss: uninitialized extern and static variables

Question #10: List the different formats of executable binaries

Answer #10: The most common formats include

  • ELF or Executable and Linking Format and 
  • COFF or Common Object File Format.

With that question, let’s end part 3 of this series. I hope it was of some value to you!

In the next part, let’s look at some questions about operating systems that you can expect on embedded interviews.

You can email us if you have any questions or suggestions. Also, you can contact us through this link.

If you liked the post, feel free to share this post with your friends and colleagues!

EI

We’re passionate about inventing embedded devices and we hope you are too! This blog deals with a wide variety of topics from C programming to IOT to networking certifications and more. Hope you enjoy your time spent here and hope you get some value out of our blog!

You may also like...