Scheduling Operating System for AVR |
|
A real time operating system (RTOS) allows
independent software tasks to be run with different priorities and to
gain access to processor resources according to each of their needs.
The RTOS manages the amount of time each task gets relative to all
other tasks. However a full RTOS with time slicing, preemption,
intertask
communication and resource locking is beyond the scope of a small
microcontroller. Here we examine a possiblility for a scheduling
operating system that is very small. The main motivation for looking to a scheduling operating system was to improve the modularity of application code. A program that executes a set of independent tasks will generally block while waiting for some external event to occur. To avoid this blocking behaviour, a state machine approach can be used, but this can grow to have quite a large number of states. While a state machine is reasonably efficient, the code quickly becomes difficult to read and hard-to-find errors can creep in. An alternative to a state machine is a scheduling operating system that allows each task to start and run, either to completion or indefinitely, relinquishing control at points in its execution when it is blocked while waiting for an external event. In a comprehensive RTOS the execution of a long task would be regularly interrupted by a timer, and the task would be forced to relinquish control in favour of other tasks waiting for the processor. To achieve this, the RTOS must save the entire state of every task, including all register and stack contents. In a microcontroller environment, the overhead associated with this is undesirable. However ,if the programmer can ensure that tasks voluntarily relinquish control at suitable points in their execution, a reasonable approximation to fair sharing can be achieved. Here is presented the design of a very
basic scheduling operating system that allows the creation, scheduling and deletion of
tasks. Because
it is not strictly a "real-time" operating system, it is referred to as
NARTOS (Not a real-time operating
system). The enclosed source file includes a
simple example task that toggles an output port. NARTOS is opensource. NARTOS CharacteristicsThe proposed operating system has probably the smallest footprint of all such operating systems. It has the following features:
Note that the term "tasks" used in NARTOS are similar to the concept of "co-routines" used by some other RTOSs. However they are not strictly the same as a co-routine as defined in Computer Science, since they do not have multiple entry points. Current StatusThe code is currently in a preliminary state. NARTOS has been made to work with C coded tasks in a comprehensive application, but its use is yet to be fully tested. Testing is being done with the avr-gcc compiler and does not guarantee the same results for other compilers. The processor being used is the ATMega88. It is expected that smaller processors would be quite useable.Existing RTOS softwareThis is probably not complete:
NARTOS DesignNARTOS consists of a single ring buffer queue. The size of
this queue will need to be kept to a minimum, however it must be long
enough to hold a single byte ID for all tasks in the program. The two
priority levels are handled by growing the queue in the opposite
direction for the high priority entries. High priority tasks are removed from the queue before any low
priority entries are removed (as you would expect), so the buffer never
becomes "scrambled".
It is generally impossible to exceed the buffer capacity (apart from
programming errors that may schedule tasks more than once) as the
number of tasks started cannot exceed the size of the buffer. Deletion of a task will free up
the table entry for reuse by
another task. The API consists of six calls,
of which one is never called from any task or ISR.
Three of these are operating system calls that leave the task and
re-enter the operating system. These will cause all program context to
be lost and
must not be called from an ISR. Tasks are all created with low
priority, and can only be rescheduled at high priority after a wait.
This avoids potential lockout of low priority tasks by a high priority
task that relinquishes.
Programming PracticeWith NARTOS
it is important
to program the tasks in a way to ensure that the program does not have
any state
variable in a register that needs to be preserved through a
relinquish or wait call. This would quite likely be overwritten due to
activities of other tasks. This is simple enough to accomplish if using
assembler, however with compiled languages it is a different story. It
is not easy to determine in general what an optimizing compiler may do
to the code. The gcc compiler tends to place local variables into
registers. The following practices must be followed ensure that no
problems occur:
Note that in NARTOS
we are
manipulating the stack in such a way that API function calls do not
behave as a compiler may expect them to do. There is a risk that
optimization may make incorrect decisions about the function call. Needless to say, using NARTOS
introduces a number of programming risks and is not appropriate where
there are a large number of local variables that would be forced into
SRAM by the above constraints. It is definitely not appropriate where
strict real-time constraints are necessary. There are other freely
available and opensource RTOS packages available, and many good
commercial ones. |
First created 19 May 2007
Last
Modified 18 June 2007