I have always characterized the difference between desktop systems and embedded along the lines of “desktops are all the same; embedded systems are all different.” Although, if I think about platform based designs, this is less universal, but the distinction still mostly holds true.
Commonly, I would cite this difference when considering the needs of embedded software engineers with respect to development tools – compilers, debuggers etc. However, it gets interesting when you start looking at operating systems …
It becomes clear that an embedded system is different from a desktop when you consider the configuration of an operating system. There are, in effect, three basic aspects to the configuration process:
- configure the OS to work properly in the specific hardware environment
- select the OS components needed for the specific application [e.g. networking, graphics etc.]
- scale the OS to provide just the services required by the application code
For a “classic” RTOS, like Mentor Embedded’s Nucleus these stages look something like this:
- (1) is a matter of obtaining and building the appropriate release of the OS for the specific CPU in use. Then a BSP [startup code and devices drivers] needs to be developed or obtained.
- Stage (2) is self-explanatory – it is just a question of obtaining the libraries for the required functionality. It would be unusual, for example, to include file system support in a system where this capability is not required.
- Since, in most embedded systems, the application code is linked to the OS, which is provided as a library, the OS code scales automatically – only support for required functionality is included in the final image as only those APIs are extracted from the library.
RTOS configuration can be a time-consuming process, so RTOS vendors have worked hard to simplify the process. Nucleus ReadyStart is an example of a product designed to get the user up and running in minutes instead of days.
Of course, a desktop computer is different. The OS is installed quite separately from application code. The basic hardware does not vary too much, so installation is largely automated. Later installation of additional hardware is commonly via USB, which is mostly plug-and-play.
Embedded Linux is somewhat in-between. It has its origins in the desktop world, but is being applied to traditional embedded applications. Linux systems are generally configured dynamically. Instead of a BSP being used to make the binary image unique and specific, libraries contain all the possible drivers etc. and the developer just needs to describe the system in a meaningful way. This is done with a Device Tree. Details of device trees and their usage can be found here and here. Here is an example of some device tree code:
compatible = "xyz,eval99";
compatible = "arm,cortex-a8";
This shows a single root node – / – which has a property “compatible” which describes the system on which the OS is to be run and, in principle, could be everything that the OS needs to configure itself. However, more information is very likely. Similar nodes are used to describe other components of the system, with appropriate levels of detail. As you can see, the syntax is rather familiar.
In a future posting, I will look in more detail at the implementation of real device tree.