Technical pages
The Real-Time kernel
Instructions
Use
Example
Principle
The
real-time kernel developed in
this system is relatively simple. The principle is to make a scan of a
task descriptors chained list every millisecond. Those
descriptors contains 5 informations by task:
- a word (16 bits) giving the task
priority level what allows to have 65535 different levels. The level
0 is reserved to the FORTH interpreter/compiler
- a word (16 bits) giving the duration in millisecondes (up to 8192) to wait before launching task. This number is
initialized in every activation of the task (instruction "
T_ACTIVE " or "T_PERIODE") and decremented at every millisecondes by the
real-time kernel. Task is launched when its value is zero and
when the priority level is superior at the level of tasks in
the course of execution. This value is put in "-1"
when task is effectively launched.
- a long word (32 bits) giving the
address of the following task descriptor.
- a word (16 bits) giving the
task periodicity in milliseconds (up to 8192) when it is initialized
with the instruction "T_PERIODE".
- a word (16 bits) giving the
next duration in milliseconds (up to 8192) to wait before lauching
again the task with the instruction "T_ACTIVE".
At every
millisecond, the real-time
kernel increments the variable "TEMPS" and scans this list pointed by
the variable "TACHE". The priority level of the current executed task
is stored in the variable "PRIORITE". The list is automatically ordered
by decreasing set of priorities in order to optimize the execution
times of the priority tasks.
If the scanned priority level is null, it considers that there is no task to manage.
Otherwise, it reads the number of milliseconds.
If the number of millisecondes is
strictly superior to zero, it decrements its and jumps to
in the following task. If it is negative, it is that task is sleepy.
If it is zero, it compares the priority level with tha
wich is memorized.
If the priority level of the new task
is lower or equal at the memorized level, the sequencer only decrements the counters of the following tasks.
In the end of the scanning, the sequencer
examines memorized address. If it is zero, it is that no task
must be launched. Otherwise, it pushs in the return stack the
priority level in the variable "PRIORITE" which is then loaded with the new
level. It launches then the execution of the new task. Once ended
task, it pulls from the return stack the previous priority level and stores it in variable "PRIORITE".
The experts will have understood it,
so that it works, the real-time kernel is recursive.
Instructions
- TEMPS
adresse
Variable containing the value of a free counter
( 32 bits) incremented all the millisecondes by the real-time
kernel
- PRIORITE
adresse
Variable indicating the current level of
priority to the real-time kernel
- T_SUSPEND
adresse
Variable allowing to suspend the real-time
kernel (if different from 0)
- TACHE
adresse
Address of the beginning of the list chained
by the tasks of the real-time kernel
- TACHE: "name" -
Task definition header, word following this
instruction gives the name of the task
This definition will be ended with the instruction
";"
WARNING: a task has to leave the stack
in the same state before and after its execution (what does no
prevent it from using it)
When task is called with its name, it returns
only the execution address
tâche
T_EXECUTE
-
Running of the specified task (used for debugging)
task, level T_AJOUTE -
Addition of the task specified in the tasks
tablewith the specified priority level (1 - 65535)
task, millisecondes T_ACTIVE -
Activation of the specified task in the specified
number of millisecondes (1 - 8192)
millisecondes,
tâche T_PERIODE -
Periodic activation of the specified task
in the specified number of millisecondes (1 - 8192)
task T_RETIRE -
Supression of the specified task from the
tasks table
- TLIST
-
List tasks managed by the real time kernel
with priority level and activation state
Use
The real-time kernel described in
this page is effective by its simplicity of functioning. This
does not go without requiring a certain rigour of the developer.
It is indeed in the developer to administer
correctly the various durations of tasks execution and their sleeping.
It is necessary to consider that the more task is priority, the
more it must be quickly executed and more the sleeping duration
must be long (proportionally) to allow the execution of the leas
priority tasks.
For example, a peripheral managemen
task will be of high priority and will content with putting into
dialogue with the system through a first in-first out stack.
On the other hand, a printing task,
relatively long because data must in dress rehearsal be converted
(picture for example) in the size of the printer which, most of
the time, is relatively slow, will be as for it of low priority
with of numerous injury time optimized according to the time of
answer of the printer.
In the system presented on this site,
all the tasks making access to the graphic screen are for the
same priority level, fixed arbitrarily to 32768, what allows to
synchronize refreshment of the various windows. The tasks peripherals
access tasks, as serial link, are so of level superior to 32768
and thorough tasks, as the printing, are of level lower than 32768.
Example
Better to dread the possibilities
of the real-time kernel, here is a simple program which uses all
the tasks management instructions.
It is about a program allowing to
emit a tone (instruction " BELL ") all the seconds.
The edition window gives the contents
of the program. Instruction " BIP_ON " declares task
" T_BIP " in the tasks table and instruction "
BIP_OFF " allows to remove it (useful when that begins to
unbearable being).

It is also possible to use the instruction T_PERIODE wich activate and run again automaticaly the task:
TACHE: T_BIP_BIP
BELL
;
: BIP_BIP_ON
49152 T_BIP_BIP T_AJOUTE 1000 T_BIP_BIP T_PERIODE
;