Rtos Details

Learning the difference between real-time and standard operating systems is as easy as imagining yourself in a computer game. Each of the actions you take in the game is like a program running in that environment. A game that has a real-time operating system for its environment can feel like an extension of your body because you can count on a specific "lag time:" the time between your request for action and the computer's noticeable execution of your request. A standard operating system, however, may feel disjointed because the lag time is unreliable. To achieve time reliability, real-time programs and their operating system environment must prioritize deadline actualization before anything else. In the gaming example, this might result in dropped frames or lower visual quality when reaction time and visual effects conflict
Methods

An operating system is considered real-time if it invariably enables its programs to perform tasks within specific time constraints, usually those expected by the user. To meet this definition, some or all of the following methods are employed:

* The RTOS performs few tasks, thus ensuring that the tasks will always be executed before the deadline
* The RTOS drops or reduces certain functions when they cannot be executed within the time constraints ("load shedding")
* The RTOS monitors input consistently and in a timely manner
* The RTOS monitors resources and can interrupt background processes as needed to ensure real-time execution
* The RTOS anticipates potential requests and frees enough of the system to allow timely reaction to the user's request
* The RTOS keeps track of how much of each resource (CPU time per timeslice, RAM, communications bandwidth, etc.) might possibly be used in the worst-case by the currently-running tasks, and refuses to accept a new task unless it "fits" in the remaining un-allocated resources.

Chapters in this section will discuss how an RTOS works, some general methods for working with an RTOS, and a few popular RTOSes. Finally, in some later chapters, we will discuss how to write your own RTOS.

Objectives

An RTOS must respond in a timely manner to changes, but that does not necessarily mean that an RTOS can handle a large throughput of data. In fact in an RTOS, small response times are valued much higher than power, or data speed. Sometimes an RTOS will even need to drop data to ensure that it meets its strict deadlines. In essence, that provides us with a perfect definition: an RTOS is an operating system designed to meet strict deadlines. Beyond that definition, there are few requirements as to what an RTOS must be, or what features it must have. Some RTOS implementations are very powerful and very robust, while other implementations are very simple, and suited for only one particular purpose.

An RTOS may be either event-driven or time-sharing. An event-driven RTOS is a system that changes state only in response to an incoming event. A time-sharing RTOS is a system that changes state as a

The Fundamentals

To most people, embedded systems are not recognizable as computers. Instead, they are hidden inside everyday objects that surround us and help us in our lives. Embedded systems typically do not interface with the outside world through familiar personal computer interface devices such as a mouse, keyboard and graphic user interface. Instead, they interface with the outside world through unusual interfaces such as sensors, actuators and specialized communication links. Real-time and embedded systems operate in constrained environments in which computer memory and processing power are limited. They often need to provide their services within strict time deadlines to their users and to the surrounding world. It is these memory, speed and timing constraints that dictate the use of real-time operating systems in embedded software.

Real-Time Kernel

The heart of a real-time OS (and the heart of every OS, for that matter) is the kernel. A kernel is the central core of an operating system, and it takes care of all the OS jobs:

1. Booting
2. Task Scheduling
3. Standard Function Libraries

Now, we will talk about booting and bootloaders later, and we will also devote several chapters to task scheduling. So we should mention at least one thing about standard function libraries: In an embedded system, there is rarely enough memory (if any) to maintain a large function library. If functions are going to be included, they must be small, and important.

In an embedded system, frequently the kernel will boot the system, initialize the ports and the global data items. Then, it will start the scheduler and instantiate any hardware timers that need to be started. After all that, the Kernel basically gets dumped out of memory (except for the library functions, if any), and the scheduler will start running the child tasks.

Basic Kernel Services

In the discussion below, we will focus on the "kernel" – the part of an operating system that provides the most basic services to application software running on a processor. The "kernel" of a real-time operating system ("RTOS") provides an "abstraction layer" that hides from application software the hardware details of the processor (or set of processors) upon which the application software will run.

Interrupts

Sometimes things will happen in a system when the processor is simply not ready. In fact, sometimes things change that require immediate attention. Can you imagine, sitting at your PC, that you were to hit buttons on the keyboard, and nothing happens on your computer? Maybe the processor was busy, and it just didnt check to see if you were hitting any buttons at that time. The solution to this problem is something called an "Interrupt." Interrupts are events that cause the microprocessor to stop what it is doing, and handle a high-priority task first. After the interrupt is handled, the microprocessor goes back to whatever it was doing before. In this way, we can be assured that high-priority inputs are never ignored.

Hardware and Software

There are two types of interrupts: Hardware and Software. Software interrupts are called from software, using a specified command. Hardware interrupts are triggered by peripheral devices outside the microcontroller. For instance, your embedded system may contain a timer that sends a pulse to the controller every second. Your microcontroller would wait until this pulse is received, and when the pulse comes, an interrupt would be triggered that would handle the signal.

Interrupt Service Routines

Interrupt Service Routines (ISR) are the portions of the program code that handle the interrupt requests. When an Interrupt is triggered (either a hardware or software interrupt), the processor breaks away from the current task, moves the instruction pointer to the ISR, and then continues operation. When the ISR has completed, the processor returns execution to the previous location.

Many embedded systems are called interrupt driven systems, because most of the processing occurs in ISRs, and the embedded system spends most of it's time in a low-power mode.

Sometimes ISR may be split into two parts: top-half (fast interrupt handler, First-Level Interrupt Handler (FLIH)) and bottom-half (slow interrupt handler, Second-Level Interrupt Handlers (SLIH)). Top-half is a faster part of ISR which should quickly store minimal information about interrupt and schedule slower bottom-half at a later time.

interrupt vector table

The "interrupt vector table" is a list of every interrupt service routine. It is located at a fixed location in program memory. (Some processors expect the interrupt vector table to be a series of "call" instructions, each one followed by the address of the ISR. Other processors expect the interrupt vector table to hold just the ISR addresses alone.)

You must make sure that every entry in the interrupt vector table is filled with the address of some actual ISR, even if it means making most of them point to the "do nothing and return from interrupt" ISR.

Memory Management

An important point to remember is that some embedded systems are locked away and expected to run for years on end without being rebooted. If we use conventional memory-management schemes to control memory allocation, we can end up with fragmented memory which can take valuable time to defragment and reallis is a major problem for tasks that are time-sensitive. This page then will talk about how to implement a memory management scheme in an RTOS, and will talk through to a basic implementation of malloc( ) and free( ).

There are a variety of ways to deal with memory:

* Some systems never do a malloc() or free() — all memory is allocated at compile time.
* Some systems use malloc() and free() with manual garbage collection.
* Some early automatic garbage collection schemes did a "stop the world" for several seconds during garbage collection and/or memory defragmentation. Such a system could miss real-time deadlines, which would be bad.
* Some later automatic garbage collection schemes do "incremental" garbage collection and memory defragmentation.

What is a Task

Embedded systems have a microprocessor connected to some piece of hardware (LEDs, buttons, limit switches, motors, serial port(s), battery chargers, etc.).

Each piece of hardware is generally associated with a little bit of software, called a "task". For example, "Check the keyboard and figure out which (if any) key has been pressed since the last check". Or "Check the current position of the spindle, and update the PID".

Often a task has a real-time limits, such as

* the motors must be shut off within 1/10 second after hitting the limit switch to avoid permanent damage
* the PID loop must be updated at least every 1/100 second to avoid oscillation
* the MP3 player must decode a new sample at 44.1 KHz — no faster, or it sounds chipmunk-like — no slower, or it sounds like it's underwater.

Some embedded systems have only one task.

Other embedded systems have a single microcontroller connected to many different pieces of hardware — they need to "multi-task".

What is the Scheduler

The "task scheduler" (or often "scheduler") is the part of the software that schedules which task to run next. The scheduler is the part of the software that chooses which task to run next.

The scheduler is arguably the most difficult component of an RTOS to implement. Schedulers maintain a table of the current state of each task on the system, as well as the current priority of each task. The scheduler needs to manage the timer too.

In general, there are 3 states that a task can be in:

1. Active. There can be only 1 active thread on a given processor at a time.
2. Ready. This task is ready to execute, but is not currently executing.
3. Blocked. This task is currently waiting on a lock or a critical section to become free.

Some systems even allow for other states:

1. Sleeping. The task has voluntarily given up control for a certain period of time.
2. Low-Priority. This task only runs when all other tasks are blocked or sleeping.

There are 2 ways the scheduler is called:

* the current task voluntarily yield()s to the scheduler, calling the scheduler directly, or
* the current task has run "long enough", the timer hardware interrupts it, and the timer interrupt routine calls the scheduler.

The scheduler must save the current status of the current task (save the contents of all registers to a specified location), it must look through the list of tasks to find the highest priority task in the Ready state, and then must switch control back to that task (by restoring it's register values from memory).

The scheduler should first check to ensure that it is enabled. If the scheduler is disabled, it shouldn't preempt the current thread. This can be accomplished by checking a current global flag value. Some functions will want to disable the scheduler, so this flag should be accessable by some accessor method. An alternate method to maintaining a global flag is simply to say that any function that wants to disable the scheduler can simply disable the timer. This way the scheduler never gets called, and never has to check any flags.

The scheduler is generally disabled inside a critical section, where we do not want to OS to preempt the current thread. Otherwise, the scheduler should remain active.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License