|
Main menu IT Visions Microprocessor Task schedule Architecture Instruction set |
Task Switching The processor contains hardware support (instructions) for a simple, but very efficient operating system like the one in the ST20. In this way, it can perform task switching much faster and much more reliable than any software based solutions. The task scheduler may be disabled if the user wants to use another operating system. There are two task priorities with each one timer queue - microsecond timers for high priority tasks and millisecond timers for low priority tasks. At any time, a task may be
Only the active task consume processor time. The task switching is based on instructions (system calls) rather than a time schedule, because this by far gives the best utilization of the system resources, but a supervisory system is build in, which switch the task if a given maximum execution time is exceeded. Task switching can only take place if the data stack is empty, so that it is not necessary to save it. This is the case no matter if the switch condition is coursed by an instruction or by the task scheduler (time out). If there is an error, so that the data stack do not get empty within a given amound of time after the switch condition, the task is disabled until next reset. The data stack pointer is common to all tasks and need not to be saved. At task switching, the PC and the status register (SR) are saved on the general purpose stack which belongs to the active task so far, as if it had been an interrupt. The accumulator (A) and the address register stack (R0-R7) are also pushed on the stack. For the address registers this is done by means of 8 dummy pushes to R0. Each task has its own workspace i memory, which holds two pointers to the workspace of the following tasks in the various queues, any timer value and the general purpose stack of that task. The stack grows in negative direction so that the positive addresses are free for any data area. If the task is not the active one, the workspace also contains a copy of the internal part of the general purpose stack and the displacement part of the stack pointer. Because the base address of the stack pointer is the same as the base address of the workspace it need not to be saved.
The task scheduler itself has a pointer to the workspace of the first
and the last task in each queue and a pointer to the first task in each
timer queue. These pointers are stored somewhere in the general purpose
register area (R8 - R255). Because a call for task switching is always
performed by an active task and the active task is the first one in the
active queue, the task scheduler has a pointer to the present workspace
and therefore knows where to save the various parts. In the same way, an
active task always knows where the workspace is because it is addressed by
the base address part of the pointer to the general purpose stack.
Communication between tasks takes place over channels. Each channel can hold one message. A task reads a message by means of the In instruction. If the message is not ready, the task is descheduled until the message is present. A task writes a message to a channel by means of the Out instruction. If the channel is not empty, the task is descheduled until the channel is ready. Note that unlike most software based operating systems it is not possible to hold more than one message in each channel, but in most systems there is actually no need for more buffering. It has no sense to supply the data faster than the receiving task can keep up with. The task may just receive old obsolete data if more data are buffered. Besides, buffer overflow or lack of message-descriptions for a new message is one of the most common error sources in most operating systems. The one-message channels may also be used for allocating system
resources. When a task wants access to such a resource, it executes an
Out instruction to a channel for that resource. Because a channel can only
hold one message the next task trying to execute an Out instruction to the
same channel will be put to sleep until the channel is ready. When the job
is done, the task executes an In instruction to the channel and in
this way frees the resource for the next task in the queue. To avoid that
a high priority task interrupts a low priority task and uses its resource,
the same resource must not be shared between high and low priority tasks.
When a task wants to wait for a given amound of time it first reads the present value of the system timer, which is a 32 bit wrap-around counter. Then it calculates the timeout time by adding the wanted delay time and writes the value to the timer position in its workspace. After that it executes the Wait instruction. This instruction puts the task in the timer queue if the specified time is in the future. The task is put into the queue in such a position, that the first task in the queue always has the shortest time before timeout. In this way, the task scheduler only has to compare the first level with the actual time. This comparision is done contineously in hardware. When the specified time becomes less than the count of the system timer, the task is applied to the back of the active queue for that task priority.
|