An Embedded System is a system that has software embedded into computer-hardware, which makes a system dedicated for a variety of application or specific part of an application or product or part of a larger system.

An embedded system can be a small independent system or a large combinational system. It is a microcontroller-based control system used to perform a specific task of operation.

An embedded system is a combination of three major components:

  • Hardware: Hardware is physically used component that is physically connected with an embedded system. It comprises of microcontroller based integrated circuit, power supply, LCD display etc.
  • Application software: Application software allows the user to perform varieties of application to be run on an embedded system by changing the code installed in an embedded system.
  • Real Time Operating system (RTOS): RTOS supervises the way an embedded system work. It act as an interface between hardware and application software which supervises the application software and provide mechanism to let the processor run on the basis of scheduling for controlling the effect of latencies.
  1. An embedded system is software embedded into computer hardware that makes a system dedicated to be used for variety of application.
  2. Embedded system generally used for do specific task that provide real-time output on the basis of various characteristics of an embedded system.
  3. Embedded system may contain a smaller part within a larger device that used for serving the more specific application to perform variety of task using hardware-software intermixing configuration.
  4. It provides high reliability and real-time computation ability.
  • Sensor: Sensor used for sensing the change in environment condition and it generate the electric signal on the basis of change in environment condition. Therefore it is also called as transducers for providing electric input signal on the basis of change in environment condition.
  • A-D Converter: An analog-to-digital converter is a device that converts analog electric input signal into its equivalent digital signal for further processing in an embedded system.
  • Processor & ASICs: Processor used for processing the signal and data to execute desired set of instructions with high-speed of operation.
  • Application specific integrated circuit (ASIC) is an integrated circuit designed to perform task specific operation inside an embedded system.
  • D-A Converter: A digital-to-analog converter is a device that converts digital electric input signal into its equivalent analog signal for further processing in an embedded system.
  • Actuators: Actuators is a comparator used for comparing the analog input signal level to desired output signal level for providing the error free output from the system.

Processors are the major part in embedded systems that take response from sensors in digital form and processing of this response to produce output in real-time processing environment is performed using processors.

For an embedded system developer it is essential to have the knowledge of both microprocessors and micro controllers.

Processors inside a system have two essential units:

  • Control unit: This unit in processors performed the program flow control operation inside an embedded system. The control unit also acts as a fetching unit for fetching the set of instructions stored inside a memory.
  • Execution unit: This unit is used for execution the various tasks inside a processors. It mainly comprises of arithmetic and logical unit (ALU) and it also include a circuit that executes the instruction sets used to perform program control operation inside processors.

Processors inside an embedded system are of the following categories:

  • Application Specific System Processor(ASSP): ASSP is application dependent system processor used for processing signal of embedded system. Therefore for different application performing task a unique set of system processors is required.
  • Application Specific Instruction Processor(ASIP): ASIP is application dependent instruction processors. It is used for processing the various instruction set inside a combinational circuit of an embedded system.
  • General Purpose Processor (GPP): GPP is used for processing signal from input to output by controlling the operation of system bus, address bus and data bus inside an embedded system.
  • Microprocessor
  • Microcontroller
  • Digital signal processor
  • Analog signal processor

A central processing unit built into a single VLSI chip is called a microprocessor. It is a general purpose device and an additional outside circuitry is added to make it work as a microcomputer.

Operations performed by microprocessor are adding, subtracting, comparing two numbers and fetching the data from memory for transferring it from one place to another.

Microprocessors is also called as Basic Input-Output system (BIOS) which used for processing the input received from sensors and produced the equivalent output from the system.

  • Arithmetic and Logic unit (ALU): ALU inside a microprocessor used to perform the arithmetic and logic operation. It performs the logic operation on the data stored inside a register.
  • Accumulator: It is a register inside which the intermediate arithmetic and logical operation data is stored.
  • Working registers: It is a storage device used to store the data inside a microprocessor in different address location.
  • Program counter: It is used for counting the number of program executed inside a microprocessor.
  • Stack pointer: Stack pointer act as a pointer to the certain address. It is a register used to store the address of the last program request made by the processor inside a stack.
  • Clock circuit: It is used for generate the clock pulse required as a reference signal for the microprocessor.
  • Interrupt circuit: It is used for generating the interrupt signal when the higher priority process required to be served first on basis of priority by microprocessor.

A microcomputer made on a single semiconductor chip is called single-chip microcomputer. Since, single chip microcomputers are generally used in control applications, they are also called microcontrollers.

Microcontroller contains all essential components of a microcomputer such as CPU, RAM, ROM/EPROM, I/O lines etc. Some single chip microcontrollers contain devices to perform specific functions such as DMA channels, A/D converter, serial port, pulse width modulation, etc.

The I/O devices of embedded system are classified into two categories

  • Serial
  • Parallel

preprocessor error directive causes the preprocessor to generate an error message and causes the compilation to fail. The #error directive is often used in the #else portion of a #if – #elif – #else construct, as a safety check during compilation.

There are several solutions to this question. My preferred solution is:

while(1)

{

}

Another common construct is:

for(;;)

{

}

A third solution is to use a goto:

Loop:

goto Loop;

(a) int a; // An integer

(b) int *a; // A pointer to an integer

(c) int **a; // A pointer to a pointer to an integer

(d) int a[10]; // An array of 10 integers

(e) int *a[10]; // An array of 10 pointers to integers

(f) int (*a)[10]; // A pointer to an array of 10 integers

(g) int (*a)(int); // A pointer to a function a that takes an integer argument and returns an integer

(h) int (*a[10])(int); // An array of 10 pointers to functions that take an integer argument and

(a) A variable declared static within the body of a function maintains its value between function invocations.

(b) A variable declared static within a module [1], (but outside the body of a function) is accessible by all functions within that module. It is not accessible by functions within any other module. That is, it is a localized global.

(c) Functions declared static within a module may only be called by other functions within that module. That is, the scope of the function is localized to the module within which it is declared.

The qualifier const can be applied to the declaration of any variable to specify that its value will not be changed ( Which depends upon where const variables are stored, we may change the value of const variable by using pointer ). The result is implementation-defined if an attempt is made to change a const.

What do the following incomplete [2] declarations mean?

const int a;

int const a;

const int *a;

int * const a;

int const * a const;

The first two mean the same thing, namely a is a const (read-only) integer. The third means a is a pointer to a const integer (i.e., the integer isn’t modifiable, but the pointer is). The fourth declares a to be a const pointer to an integer (i.e., the integer pointed to by a is modifiable, but the pointer is not). The final declaration declares a to be a const pointer to a const integer (i.e., neither the integer pointed to by a, nor the pointer itself may be modified).

 

A volatile variable is one that can change unexpectedly. Consequently, the compiler can make no assumptions about the value of the variable. In particular, the optimizer must be careful to reload the variable every time it is used instead of holding a copy in a register. Examples of volatile variables are:

(a) Hardware registers in peripherals (e.g., status registers)

(b) Non-stack variables referenced within an interrupt service routine.

(c) Variables shared by multiple tasks in a multi-threaded application.

 

Can a parameter be both const and volatile? Explain your answer.

 Yes. An example is a read only status register. It is volatile because it can change unexpectedly. It is const because the program should not attempt to modify it.

Can a pointer be volatile? Explain your answer.

 Yes. Although this is not very common. An example is when an interrupt service routine modifies a pointer to a buffer.

 

What is wrong with the following function?:

int square(volatile int *ptr)

{

return *ptr * *ptr;

}

This one is wicked. The intent of the code is to return the square of the value pointed to by *ptr. However, since *ptr points to a volatile parameter, the compiler will generate code that looks something like this:

int square(volatile int *ptr)

{

int a,b;

 

a = *ptr;

b = *ptr;

return a * b;

}

Since it is possible for the value of *ptr to change unexpectedly, it is possible for a and b to be different. Consequently, this code could return a number that is not a square! The correct way to code this is:

long square(volatile int *ptr)

{

int a;

 

a = *ptr;

return a * a;

}

 

Real-time embedded systems are computer systems that monitor, respond or control an external environment. This environment is connected to the computer system through actuators, sensors, and other input-output interfaces.

Microprocessor is managers of the resources (I/O, memory) which lie outside of its architecture

Microcontroller have I/O, memory, etc. built into it and specifically designed for control

DMA address deals with physical addresses. It is a device which directly drives the data and address bus during data transfer. So, it is purely physical address.

Interrupt latency is a time taken to return from the interrupt service routine post handling a specific interrupt.  By writing minor ISR routines, interrupt latency can be reduced.

For embedded system, the buses used for communication includes

  • I2C: It is used for communication between multiple ICs
  • CAN: It is used in automobiles with centrally controlled network
  • USB: It is used for communication between CPU and devices like mouse, etc.

While ISA, EISA, PCI are standard buses for parallel communication used in PCs, computer network devices, etc.

Timers in embedded system are used in multiple ways

  • Real Time Clock (RTC) for the system
  • Initiating an event after a preset time delay
  • Initiating an even after a comparison of preset times
  • Capturing the count value in timer on an event
  • Between two events finding the time interval
  • Time slicing for various tasks
  • Time division multiplexing
  • Scheduling of various tasks in RTOS

A watchdog timer is an electronic device or electronic card that execute specific operation after certain time period if something goes wrong with an electronic system.

Embedded systems require infinite loops for repeatedly processing or monitoring the state of the program.  For instance, the case of a program state continuously being verified for any exceptional errors that might just happen during run-time such as memory outage or divide by zero, etc.

Some of the commonly found errors in embedded systems are

  • Damage of memory devices static discharges and transient current
  • Address line malfunctioning due to a short in circuit
  • Data lines malfunctioning
  • Due to garbage or errors some memory locations being inaccessible in storage
  • Inappropriate insertion of memory devices into the memory slots
  • Wrong control signals

A semaphore is an abstract datatype or variable that is used for controlling access, by multiple processes to a common resource in a concurrent system such as multiprogramming operating system.  Semaphores are commonly used for two purposes

  • To share a common memory space
  • To share access to files

__interrupt double compute_area(double radius) {

double area = PI * radius * radius;

 

printf(“nArea = %f”, area);

return area;

}

 

Interrupt service routines cannot return a value. If you don’t understand this, then you aren’t hired.

ISR’s cannot be passed parameters. See item (a) for your employment prospects if you missed this.

On many processors / compilers, floating point operations are not necessarily re-entrant. In some cases one needs to stack additional registers, in other cases, one simply cannot do floating point in an ISR. Furthermore, given that a general rule of thumb is that ISRs should be short and sweet, one wonders about the wisdom of doing floating point math here.

In a similar vein to point (c), printf() often has problems with reentrancy and performance. If you missed points (c) & (d) then I wouldn’t be too hard on you. Needless to say, if you got these two points, then your employment prospects are looking better and better.

void foo(void)

{

unsigned int a = 6;

int b = -20;

(a+b > 6) ? puts(“> 6”) : puts(“<= 6”);

}

This question tests whether you understand the integer promotion rules in C – an area that I find is very poorly understood by many developers. Anyway, the answer is that this outputs “> 6”. The reason for this is that expressions involving signed and unsigned types have all operands promoted to unsigned types. Thus –20 becomes a very large positive integer and the expression evaluates to greater than 6. This is a very important point in embedded systems where unsigned data types should be used frequently (see reference 2). If you get this one wrong, then you are perilously close to not being hired.

unsigned int zero = 0;

unsigned int compzero = 0xFFFF; /*1’s complement of zero */

On machines where an int is not 16 bits, this will be incorrect. It should be coded:

unsigned int compzero = ~0;

This question really gets to whether the candidate understands the importance of word length on a computer. In my experience, good embedded programmers are critically aware of the underlying hardware and its limitations, whereas computer programmers tend to dismiss the hardware as a necessary annoyance.

By this stage, candidates are either completely demoralized – or they are on a roll and having a good time. If it is obvious that the candidate isn’t very good, then the test is terminated at this point. However, if the candidate is doing well, then I throw in these supplemental questions. These questions are hard, and I expect that only the very best candidates will do well on them. In posing these questions, I’m looking more at the way the candidate tackles the problems, rather than the answers. Anyway, have fun…

Here, I expect the user to mention memory fragmentation, problems with garbage collection, variable execution time, etc. This topic has been covered extensively in ESP, mainly by Plauger. His explanations are far more insightful than anything I could offer here, so go and read those back issues! Having lulled the candidate into a sense of false security, I then offer up this tidbit:

What does the following code fragment output and why?

char *ptr;

if ((ptr = (char *)malloc(0)) == NULL) {

puts(“Got a null pointer”);

}

else {

puts(“Got a valid pointer”);

}

This is a fun question. I stumbled across this only recently, when a colleague of mine inadvertently passed a value of 0 to malloc, and got back a valid pointer! After doing some digging, I discovered that the result of malloc(0) is implementation defined, so that the correct answer is ‘it depends’. I use this to start a discussion on what the interviewee thinks is the correct thing for malloc to do. Getting the right answer here is nowhere near as important as the way you approach the problem and the rationale for your decision.

#define dPS struct s *

typedef struct s * tPS;

The intent in both cases is to define dPS and tPS to be pointers to structure s. Which method (if any) is preferred and why?

This is a very subtle question, and anyone that gets it right (for the right reason) is to be congratulated or condemned (“get a life” springs to mind). The answer is the typedef is preferred. Consider the declarations:

dPS p1,p2;

tPS p3,p4;

The first expands to

struct s * p1, p2;

which defines p1 to be a pointer to the structure and p2 to be an actual structure, which is probably not what you wanted. The second example correctly defines p3 & p4 to be pointers.

This question is intended to be a lighthearted end to the quiz, as, believe it or not, this is perfectly legal syntax. The question is how does the compiler treat it? Those poor compiler writers actually debated this issue, and came up with the “maximum munch” rule, which stipulates that the compiler should bite off as big a (legal) chunk as it can. Hence, this code is treated as:

c = a++ + b;

Thus, after this code is executed, a = 6, b = 7 & c = 12;

If you knew the answer, or guessed correctly – then well done. If you didn’t know the answer then I would not consider this to be a problem. I find the biggest benefit of this question is that it is very good for stimulating questions on coding styles, the value of code reviews and the benefits of using lint.