Computers are found in many places. We use them in our offices and in our homes, and we carry them in our pockets. Some computers are visible, such as laptops or desktop computers. Many computers are hidden, invisible to us, inside other systems. These built-in computers are referred to as embedded computers.
There are embedded computers in your phone, performing tasks such as making phone calls and helping you to connect to the Internet. There are also embedded computers in your TV, in your car, and most likely also in your washing machine. These types of systems, in which there are embedded computers, are often referred to as embedded systems.
This is a book about embedded systems. It shows you how to do programming for embedded systems. The book assumes that you have some previous experience from programming. The book also assume that you have a basic understanding of how a computer processor works.
If you have programming skills corresponding to one or two courses at a university, you will be sufficiently prepared. Of course you will be equally well prepared if you have acquired these skills by other means, e.g. at work or as a hobbyist programmer.
When programming embedded systems, it is helpful to have knowledge of the underlying hardware. For this book, you need to understand how a processor executes programs, by reading instructions from memory, and taking actions depending on which instructions it reads. Additional knowledge in the hardware area, such as knowledge about computer peripherals and buses, would be beneficiary - however not necessary - for a successful journey through the book and its contents.
An embedded system interacts with its environment. Many embedded systems actively control some aspect of their environment, such as adjusting the heater in your house during winter, or adjusting ailerons in an aircraft while the aircraft is flying.
Many embedded systems also measure some aspect of their environment. This is the case in a measurement system, for example a temperature measurement system indicating the temperature of a room in your house. In an embedded system performing a control task, the measurements are used also as support for decisions to be taken, such as the decision to increase heat water flow in order to increase the room temperature, or the decision to move an ailerion in a certain direction, for the purpose of keeping an aircraft on its desired course. These decisions are referred to as control actions. The control actions are determined by combining the measurements, in these cases the measured room temperature or the measured heading of an aircraft, with desired values for the measured quantities. The combination is typically done inside an algorithm. The algorithm calculates the exact amount of control action to use. In this way, an embedded system can be said to be reactive, since its actions are based on stimuli, in the form of measurements, from its external environment.
Inside embedded systems, there is software. The software executes on the embedded computers, in systems such as aircrafts, phones, television sets, and cars. The software may be large, in the sense that it has many lines of code. The actual amount of code may vary from a few thousand lines in a small embedded system, to several million lines of code, which is the case for a mobile phone of today.
This is a Book with Views. This means that the book covers several types of computers at the same time. When you read the book, you read it one view at the time, and you can easily switch betwen the views. There are links to the views at the end of each section, and in the web version of the book there are also links to the views in the left sidebar of each page. The view you are currently reading is about computers with a processor architecture called the x86 architecture. This architecture was originally created by Intel, and it is commonly found in personal computers, but also in embedded systems. Here we describe the 32-bit version of the architecture.
The programming language C is used. The reason for choosing C is that most embedded systems are programmed in C. This is so even if the language itself is rather old. In addition to C, assembly programming is used. The reason for choosing assembly is that it is required for certain things involved in the creation of an embedded system. Among these things are the startup of a system, the handling of interrupts, communication with external devices, and the switching between different actitivites in a program.
A specific hardware is chosen, for the purpose of making examples more realistic, and for making them repeatable, so that readers can do experiments. This book uses the hardware found in a personal computer. This means that you can, if you dare, boot your own personal computer with software developed as described in this book. For the purpose of simulation, which is very convenient when developing the software, the simulator QEMU is used.
In the early days of computing, there were no operating systems. The programmer wrote a program that executed directly on a computer. This type of programming is done also today, typically in embedded systems. The reason for not using an operating system in an embedded computer could be safety regulations, but it could also be size, in the sense that the computer used is too small to make it cost-effective to use an operating system.
Computers running without operating systems can be said to run programs on the bare metal. Such programs can be developed, and executed, also on modern computers. The task of making a bare-metal program for a 32-bit Intel-x86-compatible processor is described in the book chapter The Bare Metal.
It is shown, in chapter The Bare Metal, how a bare-metal program can be constructed, and how it can be made to execute. The exercise of creating a bare-metal program for a computer where an operating system is normally used can be both rewarding and challenging. It will also give you insight in how hardware and software operate together, with a focus on the early phases of program execution, directly after the computer is started.
The interactions between software and hardware are further elaborated in chapter Hello world. The chapter Hello world presents an analysis of the program from chapter The Bare Metal, and the assembly instructions corresponding to the C statements used in the program are described.
The relations betwen statements in the C programming language and the corresponding assembly instructions are described more systematically in chapter C and Assembly. A selection of the available assembly instructions in a 32-bit Intel-x86-compatible processor is presented. It is also described how assembly instructions are used when performing function calls and returns from function calls, and how parameters to functions are handled.
Embedded systems often react to events from the outside world by receiving interrupts. The interrupts are generated when events occur. Example events could be that a new measurement value is ready, or that a new data item is available on a communication channel. The interrupts are generated as electrical signals, which while passing through a dedicated electronic compoment, often referred to as an interrupt controller, are converted to a format suitable for the computer used. The resulting effect is that an event is generated, such that the flow of execution is interrupted. The program then continues, for a short while, by executing a dedicated routine, referred to as an interrupt handler.
The task of an interrupt handler is to perform immediate actions that are necessary, such as storing an incoming measurement value or an incoming data communication value in a storage buffer. When the interrupt handler has finished its task, the ordinary execution of the program continues, at the point where it left off when the interrupt occurred.
Interrupts, and interrupt handlers, are described in chapter Interrupts.
Programs executing on a computer peform their work mostly on behalf of the computer's processor. The processor, which in this book is a a 32-bit Intel-x86-compatible processor, reads instructions, in binary form but possible to describe using assembly language as shown in chapter C and Assembly. For each instruction read, the processor takes actions. The actions depend on the specific instruction read, but also on data available to the processor.