There is a class of systems that need to carry out multiple concurrent activities in order to accomplish the application objectives. Some of these activities may have timing deadlines and hence may have to be given a priority over the others. Such systems use a real-time operating system (RTOS), which allows implementing the system as multiple tasks and execute them according to their priorities. Since meeting the deadline is critical, such systems are known as real-time systems.
2. Real-time Systems
To understand multitasking, let us take an example of an internet music player. Here, we are talking about an embedded system with a microcontroller, some on-chip memory, some off-chip memory and a few peripheral devices. The microcontroller would typically run at a few tens of MHz. The RAM could range from a few tens to a few hundreds of kilobytes. The ROM / flash could be a few tens of kilobytes, either on-chip or off-chip, to store the program. The peripherals would be a Wi-Fi chip to connect to the internet, a high quality DAC (Digital to Analog Converter) that can play 44100 (or more) stereo samples of music every second, an LCD to show the details of the songs being played and a few buttons for user controls such as play, stop, next track, previous track and changing volume.
The software requirements for such a system would be more demanding compared to those of a single task system. The system is required to perform multiple tasks at the same time: (1) receive data packets from the server, (2) uncompress the music data, (3) transmit music samples to the DAC and (4) display the song details on the LCD and control music playback according to the user inputs. Each task here has a different timing requirement. The network task needs to talk to the server to receive the next packet, otherwise there may not be adequate music to play. The music samples have to be transmitted at the rate of 44100 samples per second for playing music continuously. If these tasks are performed sequentially one after the other, the system may not be able to meet the timing requirements for all the tasks. And if any of these tasks doesn’t happen on time, the music produced would be full of clicks and breaks, which won’t be music at all!
Therefore, a multitasking system requires Real-Time Operating System (RTOS) which can execute the right task at the right time, thereby meeting timing requirements of all the tasks. Unlike a desktop operating system, an RTOS does not have complex memory management and file system requirements, but it has to be compact in size and fast in execution. Hence, an RTOS contains minimal features that support multitasking, and therefore, it is also often referred to as a real-time micro kernel.
Examples of similar systems are a car engine control unit, an ECG machine or robotic vacuum cleaner. All of them are tuned towards one specific application, and they require multiple tasks in order to meet the overall system timing requirements. We classify such systems as multitasking systems.
Tasks
A multitasking system is implemented as one single program, consisting of multiple application tasks and an RTOS. A task typically runs a loop that keeps receiving inputs, processing them and generating the outputs. This is similar to the main loop in a single-task system, except that the main loop communicated with the IO devices for its inputs and outputs, whereas a task in a multitasking system could communicate to an IO device or another task for its inputs and outputs.
Scheduler
The scheduler is a piece of code that runs as a part of the RTOS. Its job is to stop the current task and run the next task. The scheduler schedules the tasks according to their priorities. Most RTOS run a priority based scheduler, which always schedules the highest priority task that is ready to run. The scheduler runs lower priority tasks only when higher priority tasks are waiting for their inputs. Whenever a high priority task gets its inputs and becomes ready to run, the RTOS stops a lower priority task and switches to the higher priority task. By doing so, the RTOS ensures that the time-critical tasks run as soon as their inputs are available, thereby meeting their timing requirements.
Co-operative multitasking
In a standalone system, the activities happen one after the other. As we discussed earlier, time consuming activities become bottlenecks. This is shown in the diagram below.
The diagram shows the response time for two activities a1 and a2. They receive two inputs (i1 and i2) and produce two outputs (o1 and o2) after t1 and t2 time respectively. In the first scenario, the activities are strictly sequential - there is sufficient time gap between the two for the activities to complete and generate the output. The response time for the two activities are r1=t1 and r2=t2 respectively.
In the second scenario, two activities overlap. As a result, even though i2 is available much earlier, a2 can start only after a1 completes. Hence, the response time for a2 is much larger than t2. If i2 was available soon after i1, then r2 would be almost equal to t1+t2. This could be a serious limitation, especially if a2 is time-critical and a1 take a long time.
The diagram below shows how this scenario is taken care of by having a real-time scheduler. The activity a1 is scheduled as soon as i1 is available. While a1 is in progress, i2 becomes available. Instead of waiting till a1 completes, the scheduler preempts a1 and schedules a2, allowing it to process i2 immediately and generate o2. Once a2 completes, the scheduler schedules a1, which then continues processing i1 and generates o1.
Such a scheduler is called preemptive priority scheduler because it preempts lower priority task and schedules higher priority task. The lower priority task now gets stretched because it was preempted, but that may be an acceptable trade-off in order to meet a2's deadline.
Earlier, we said that a single task system is like a single lane bridge, where only one vehicle can pass at a time. A multitasking system is also like a single lane bridge, where only one vehicle can pass at a time, but we can choose which vehicle can pass first. RTOS scheduler is like a giant crane which can place the most time-critical vehicle on the bridge. Now if a bullock cart is crossing the bridge when an ambulance needs to cross the bridge, the scheduler can place the bullock cart aside (without hurting the bull, of course!) and place the ambulance on the bridge. Once the ambulance crosses the bridge, the scheduler places the bullock cart back in its original position and lets it go - until another faster vehicle comes by!
Inter-task Communication
In a multitasking system, the tasks run concurrently - meaning they progress at the same time. Even though they run independently, all of them need to operate together to fulfill the application requirements. Hence, there would be a need for mechanism that facilitates communication between tasks.
There are broadly two scenarios that for which inter-task communication is required: synchronization and mutual exclusion.
Synchronization is required when one task (say, consumer task) consumes data produced by another task (say, producer task). In which case, the consumer must wait for the producer to produce the data. RTOS provides a mechanism by which the consumer task can indicate that it needs to wait for data and producer can inform the consumer that the data is ready.
Mutual exclusion is required when multiple tasks operate on the same resource. A resource could be data or an IO device. If the scheduler switches out the task which is in the middle of a shared resource, and the switched in task starts using the same resource, then the resource could get into an inconsistent state. For this purpose, RTOS provides function calls to be used while using shared resources.
RTOS provides a collection of objects which are called by a task when it needs to communicate with other tasks. The exact number and names of these objects vary from one RTOS to other. The most common ones are semaphores and message queues. Semaphores can be used for synchronization (the consumer waits for a semaphore until the producer posts a semaphore) and mutual exclusion (any task must acquire a semaphore before using a shared resource). Message queues are used for a producer task to pass data to a consumer task.
Inter-task communication call the scheduler as and when required. For example, if a task calls a wait call, wait call in turn calls the scheduler so that other tasks can be scheduled until the producer produces data. Likewise, if a task is using a common resource, the scheduler does not schedule any other task that needs to use the same resource.
Software architecture
The figure below shows the software architecture of a system running an RTOS. The system consists of startup code and main code. The main code consists of RTOS functions and application tasks as shown in the figure below.
The startup code initializes the system and then jumps to a startup task. The startup task creates all the other tasks in the system and then gives the control to the scheduler. When they need to communicate with one another, they use inter-task communication functions provided by the RTOS. These functions call the scheduler if there is a change in the state of any of the tasks. The scheduler, then schedules the next task according to the task priorities and states.
Task creation function, scheduler and inter-task communication functions form the OS code (shaded grey in the diagram) whereas all the tasks and ISRs form the application code in such a system.
Real-time Operating System (RTOS)
The term "Operating System" often gives us a picture of a very complex piece of software such as Linux or Android that always runs on a computer and allows us to run applications such as an email or a web browser. RTOS is not that kind of an operating system - in fact, calling it an OS is perhaps an overstatement. RTOS is actually a set of routines that facilitate multitasking. Unlike a desktop operating system which resides on the computer all the time, RTOS is actually "embedded" inside the application code. The RTOS functions are linked with the application pretty much in the same way as we link string functions of math functions. Once the startup code boots up the system, it gives control to the startup task, which creates all the tasks in the system. These tasks keep running according to their priority and use the inter-task communication functions as required. The scheduler runs only when there is a change in the state of a task from ready to waiting or vise-versa.
Memory map
Hardware configuration for real-time systems is similar to that of a standalone system. Memory requirement for an RTOS is not much - it ranges from a few hundred bytes to a few tens of kilobytes. RAM required depends on the number of tasks and inter-task communication objects used in the system - typically a few hundred bytes to a few kilobytes. The memory requirement is small enough for the system to fit into on-chip flash of a microcontroller.
All the tasks, scheduler and inter-task communication code is compiled together to form a single program. Hence all of them share the same code and data. Since the tasks run concurrently, they have independent stacks so that each task can have its own flow of function calls. Other than that, the memory organization is similar to that of a standalone system.
Depending on the memory requirement of the application code, there are two possible configurations: one, the system running from the on-chip memory and two, the system running from external memory.
Smaller systems have code and read-only data residing in on-chip ROM / flash memory. This code uses RAM for read-write data. Additionally, there is one stack for each task to store local variables, arguments etc. for function calls.
In the system where the code cannot fit into on-chip memory, the code is stored in a compressed form in on-chip ROM / flash memory. If the code size is even larger, then it is stored in secondary memory such as an SD card. The system contains boot code that starts up the system, initializes off-chip memory device and copies the operational code either after uncompressing it or reading it from secondary memory as the case may be.
Once the code is copied in RAM, the boot code jumps to the startup task, which creates all the tasks in the system and gives the control to the scheduler, which then schedules tasks according to their states and priorities and the system then runs happily ever after.
(Coming soon) next: embedded Linux >
Comments
Post a Comment