Beruflich Dokumente
Kultur Dokumente
By definition an operating system is supposed to control the computer upon which it is running. It parcels out the resources of the system to programs that ask nicely and rejects or delays those that dont make the cut. The movie TRON characterized the Master Control Program as a megalomaniacal dictator that arbitrarily interfered with the peaceful lives of programs running within its purview. Laying such anthropomorphism aside, it is easy to see how a typical desktop computer user could identify with characterizations like this. Most operating systems exercise a large degree of control over the programs and resources being used by a computer, and sometimes that control appears to be wielded arbitrarily or even malevolently. But the relationship of the operating system and the application software in a typical embedded system is much simpler in some ways and much more complex in others. There are specific requirements that grow out of the dedicated environment that simply arent present in the multipurpose world of desktop or larger computers. This paper will explore that relationship and what makes some operating systems much more appropriate to embedded systems and where it might be appropriate to press desktop operating systems into service for embedded systems.
Really Real-Time
The most apparent dividing line usually revolves around the phrase real-time. Most of the operating systems that are specifically targeted to the embedded world are characterized as Real-Time Operating Systems (RTOS) and much is made of that distinction. But what exactly does that mean? There are also desktop operating systems that have priority levels that are characterized as real-time. Are these the same thing? What does real-time mean anyway? Do other operating systems run in imaginary time? Are RTOSs just very fast operating systems?
Revisiting fast
The RTOS market is very competitive and very fragmented. Each vendor is therefore looking for any advantage they can get. Given this, it is to be expected that the major RTOSs are both deterministic and very fast. The critical sections of code in each RTOS have been optimized and reoptimized, to the point where there is very little difference between the speed that different RTOSs take to do these critical functions. There is a price to be paid for this speed, however. It is basically the difference between the family station wagon and an Indy 500 racecar. The former is very good at taking care of Grandma as she drives to the market on Sunday, but the latter will do 200 MPH. Each of these is adapted to the requirements of the environment. In other words, the programmer should not assume that a typical RTOS will have all of the niceties of a desktop operating system. The way this racecar obtains that speed id by stripping out everything that is not absolutely essential to achieving maximum speed. This has the added advantage of reducing the memory footprint of the RTOS. Most desktop operating systems these days require multiple megabytes of RAM to operate, while a minimally-configured RTOS kernel can often run with just a few tens of kilobytes. Granted, RAM is much cheaper these days than has been the case in the past, but many embedded systems are still very sensitive to price.
Multitasking/Multithreading
The most commonly used feature of any given RTOS is easily multitasking. This powerful tool allows a programmer to interleave operation of relatively unrelated portions of the application code at a very high granularity. This creates the illusion that the system is doing multiple things at once, a very useful capability for a programmer with a complex set of requirements to implement. But there are two primary models for multitasking. The multithreading model is the simplest and fastest (and therefore the most popular in many applications), while the multiprocessing model is the most robust. Each of these is examined in more detail below.
Multiprocessing model
This is the model typically used in desktop operating systems. Each task has a distinct code and data space and these boundaries are typically enforced by hardware memory management. The communications methods between processes typically involve the operating system to a much higher degree, as do most other forms of I/O. Essentially, this is desktop computing done on embedded systems. The operating system takes a much more commanding role over the application code, which means that it now has the capability to shut down and restart misbehaving processes. The downside, of course, is increased overhead. At a minimum there is a runtime cost for accessing memory through a virtual memory translation on the CPU. There is also an extra step necessary for each context switch where the new memory context is established. The time to perform these functions is relatively small on modern CPUs, but if your application is pushing the CPU to the limit even small time deltas can be critical.
Multithreading model
The alternative is a simpler multithreading model. This model has been co-opted into many desktop environments to allow multiple threads of operation within a single process. In the embedded world it has acted as the primary means of multitasking for RTOSs like pSOS and VxWorks that follow the racecar motif described above. In this model each of the tasks shares the code and primary data space with all other tasks in the system. In other words, the only data area that distinguishes one task from another is the stack that is being used at the time. Any normal static global variables are shared and ultimately accessible from any other task. Therefore, pointers to data items can be used very freely within this type of environment without the virtual to physical translation that is necessary in the multiprocessing model.
Which is better?
This is the inevitable question, and the inevitable answer is simply It depends. Multithreading has a relatively long history in the embedded world and has been the correct answer for many applications. The dominating reason for this is the relative simplicity that it brings to intertask communication and the lower overhead that it entails. Add to this the reduced system cost in terms of simpler CPUs and less memory and it seems like the hands-down winner. But there are the issues of more complex applications and higher reliability requirements. These have raised the bar in some applications to the point where they can no longer afford the simplicity of the multithreading model. It is a very different job to debug an application written by two or three programmers with a dozen or so tasks then it is to debug one written by a dozen programmers with a hundred or more tasks. If the latter project is done without the protection of memory access control there had better be some strict coding standards in place. As usual, there is no easy answer for the vast majority of applications, but the ones on either end are relatively simple. A relatively simple system that has tight cost constraints will probably go with a multithreading model, assuming there is a need for multitasking at all. A complex multimegabyte application with very high reliability requirements will probably go with a multiprocessing model. In between there is a lot of latitude for selection by systems engineers.
Peripheral Support
Another way that an RTOS brings value to a system is in the organization of code that interfaces to peripheral devices. This partitioning is very useful to extend the life of a system by allowing it to adapt more easily to new devices. It also simplifies the focus of the applications programmers, since they can follow familiar methods to access devices.
Conclusion
The RTOS world is a complex one. The needs of the customers are widely varied, with some needing only a minimal kernel capability and some online documentation and others needing a full-blown development system and training classes followed by periodic consultation. Any company that attempts to cover the whole space runs the risk of stretching itself very thin. But the essentials of an RTOS itself and how to work with it are relatively straightforward. The key is to understand what an RTOS is and what it is not. There are no magic instruction opcodes available to the RTOS vendor that cannot be used by applications programmers in most embedded systems, so having a separate RTOS from the application is a choice, not a necessity as it is in the desktop world. I believe it is usually a wise choice, in that it divides and therefore simplifies the task that must be done to create a complex system, but the ultimate choice is up to the individual system designer. If you choose to separate your application into system software and application software, the next choice is whether to build or buy the system part. The embedded world has a long history of NIH (Not Invented Here) syndrome, but I think they have to get over that in order to meet the demand for new systems and quick revisions to old systems. This does not mean that you must automatically go to the nearest RTOS vendor and write them a check. There are public domain options available or there is always the choice of writing your own RTOS. If you select that path, however, please make sure you completely understand the support and other costs that are involved. It may turn out that that commercial RTOS is cheaper in the long run!