Let’s be honest, for most, the phrase Embedded System does not elicit much excitement…which is unfortunate. This somewhat sterile term is used to describe a broad category of computer applications that are an integral part of our everyday lives. For me, embedded systems represent some of the most exciting computer engineering applications where the proverbial computing ‘rubber’ hits the real-world ‘road.’
There are many unofficial definitions of embedded systems but most boil down to some version of the following:
A computer system that is optimized to perform a finite set of specific tasks.
It is worth pointing out that this definition is focused on the functional purpose of a computer system. It does not include any reference to the system size, number of components, or end product. Also, this definition does not include small single-board computers like Raspberry Pi and PC104. Both are powerful general-purpose, stand-alone computers capable of performing many tasks but not optimized for a set of specific tasks.
So why are embedded systems so important? As I mentioned above, embedded systems are where the rubber hits the road. These are the computer systems that operate in the world beyond a personal workstation, laptop, or gaming console. Embedded Systems are also where the vast majority of the small CPUs and micro-controllers are used. According to this Wikipedia article, 98% of all micro-controllers are part of embedded systems.
Wikipedia contains an overview and history of embedded systems here. I always find formal definitions of limited value and prefer to teach using examples. Some examples of embedded systems we encounter every day are:
Automobiles
Thermostats
Refrigerators
Digital Clocks
Digital Cameras
Computer Disk Drives
Computer Modems
Electronic Toys
Personal Music Players
DVD Players
Televisions

The list is nearly endless.
Now that we’ve established what defines an embedded system lets dive into the components of an embedded system and some of the challenges faced when designing them.







Many embedded systems must react or respond to events in a well defined, limited amount of time. We call these real-time computing systems. While efficient code design is always important, most computer programs do not face real-time constraints. For most applications, the exact execution time does not define success or failure as long as the program generates the expected results. If a block of code executes in X milliseconds or Y milliseconds, as long as the code provides the correct output. For example, most users don’t care if a disc drive system responds to a read request in 0.5 milliseconds or 0.55 milliseconds, as long as the program returns the correct data. Similarly, if your embedded system is monitoring the temperature of a cooler and turning on and off a refrigeration system to maintain temperature, it probably doesn’t matter if the control system checks the temperature every 5 seconds or every 10 seconds.
Ask John or Jane Doe off the street for a definition of Bare Metal and you would likely hear about AC/DC crossed with the Full Monte. In embedded systems parlance, Bare Metal refers to systems that run on the hardware platform without the support of a commercial operating system. Bare Metal systems make up the vast majority of applications in the real world. Running programs native on the CPU or micro-controller creates some interesting challenges that developers don’t face when they have the support of an operating system.
For some who are new to bare metal, this may sound like an existential philosophical question, but trust me, it’s not. In fact, this is a question that I often use as an interview question. Or maybe better said, what happens and what needs to happen before main(). While some details are platform-dependent, the process is similar for most systems. After power-up, the processor starts execution at some known address. In ARM’s case, it starts by securing the reset exception/reset vector and runs the code at that program address.
The CPU or micro-controller in any embedded system provides the foundation for the entire design. The selection must satisfy all the design requirements listed in the Introduction. There are literally thousands of options for CPUs. Designers typically pay close attention to new offerings from chip manufacturers.
Firmware is a hardware-specific program that is closely coupled to the hardware and essential for proper operation of the system. It is stored on the hardware portion of the system and is loaded when the system is powered on. The firmware programs must be compiled (translated) into chip level instructions (machine code) that is specific to the hardware platform. Because we are talking about compact systems optimized for a specific application, the firmware typically only contains the logic required to complete the required task. 