[previous]
[index]
[next]
Example 3: Variable-Period Scheduling of a Single Task
This example demonstrates a single task that toggles the
speaker port with a continuously varying frequency. Since there is no
identifiable base period for the timer, we'll put it in one-shot mode
and change the task period each time it runs. This adds some minor
overhead (about 2 microseconds) each cycle for timer reprogramming,
but it avoids quantization of the speaker frequency to some base timer
frequency. Refer to the commented
source code of the example for the details.
Principle of Operation
- In the previous examples, we established each pure periodic task's
period as an argument to 'rt_task_make_periodic()'. This was done once
at the beginning, in 'init_module()'.
- Then, in the task code, we called 'rt_task_wait_period()' at the
end of each cycle, to put it to sleep and await the next cycle.
- In the task code here, we'll call 'rt_sleep(RTIME delay)' with an
explicit delay, which can vary each cycle.
- We still call 'rt_task_make_periodic()' to start the task, but we
can use a dummy value as the base period, since there is none.
Setting up the Timer
Setting up the Task
- The task is set up as before, calling 'rt_task_init()' and
'rt_task_make_periodic()'.
- In the task function, however, we need to call 'rt_sleep(delay)'
with 'delay' set to the time, in counts, that we want to delay the
task. Calling 'rt_task_wait_period()', as before, will cause it to
sleep for the dummy period provided earlier, which is not what we
want.
- The sound will now sweep continuously up and down as the delay is
changed.
The Task Function and Timing
- Each cycle, the task function computes the amount of delay until
the next cycle,
following a relatively simple algorithm that adds or subtracts some
increment tuned to sound good for this example.
- In order to improve the timing, the task function reads its actual
start time to use as a basis for computing the delay. While this is
not really necessary for this example, it introduces the function
RTIME rt_get_time(void);
which returns the number of counts since RTAI booted, as an RTIME,
which is a long long int, rolling over into negative territory at 63
bits.
- In periodic mode, a 'count' is one tick of the 8254 timer chip, or
1,193,180 counts per second. This gives rollover at
263/1,193,180 seconds, or over 200,000
years. No need to worry about rollover here.
- In one-shot mode, a 'count' is one tick of the CPU clock, say
1 billion counts per second on a 1 GHz machine. This gives rollover at
263/1,000,000,000 seconds, or about 70
years. No need to worry about rollover here either.
- On an embedded system powered up for many years, you'd need to
worry. This means checking if a new timestamp was less than a previous
one, and subtracting the difference from the range to get the true
difference.
Running the Demo
To run the demo, change to the 'ex03_variable' subdirectory of the
top-level tutorial directory, and run the 'run' script by typing
./run
Alternatively, change to the top-level tutorial directory and run the
'runall' script there by typing
./runall
and selecting the "Single Variable-Period Task" button.
You'll hear a continuously varying tone for about 10 seconds.
See the Code
Next: Example 4, FIFOs
Back: Example 2, Pure Periodic
Scheduling of Two Tasks