[previous]
[index]
[next]
Example 12: Floating Point in Real-Time Tasks
This example demonstrates how to use floating-point math in real-time
tasks. Aside from loading the RT Linux math library, which is done
in the usual "insrtl" script along with support for scheduling, FIFOs,
etc., you need to signify that you want the floating point unit (FPU)
registers to be saved and restored by RT Linux. Otherwise, these are
left alone, and the use of the FPU by an RT task will clobber the
floating point calculations of any Linux program. This is never
desirable behavior, so always make sure to enable FPU save/restore in
your RT task if you use floating point.
Refer to the commented real-time
source code and the commented application
source code for the details.
Principle of Operation
- When the RT Linux scheduler interrupt service routine runs, it
saves the context of the currently executing Linux process, including
microprocessor registers and the stack frame. When it's done with the
RT tasks, it restores them so the interrupted Linux process can resume
correctly.
- However, by default RT Linux does not save/restore the context of
the floating-point unit (FPU). This is because it takes more time to
do so, and many RT tasks don't use the FPU.
- To tell RT Linux that normal Linux applications will use the FPU
(e.g., the calculator, Matlab, etc.), call
rt_linux_use_fpu(1); /* tell RT Linux that Linux wants the FPU saved */
This can be done once during the initialization of your RT
application. If you know in advance that no Linux process will be
using floating point, you can omit this.
- Each task that uses floating point must also set a flag indicating
that FPU context must be saved and restored when it runs. This can be
done by passing an argument to 'rt_task_init()', e.g.,
rt_task_init(&rt_task, task_code, initial_arg, STACK_SIZE, RT_LOWEST_PRIORITY,
1, /* uses floating point unit */
signal_handler);
Alternatively, the task can selectively turn FPU context handling off
and on during execution, for example to speed things up in sections
where no floating point will be done, by calling 'rt_task_use_fpu()', e.g.,
rt_task_use_fpu(1); /* tell RT Linux that this task will use the FPU */
- This demo sets up a single periodic task that increments a
floating point value by some small amount, computes the sine and
cosine, and increments a cumulative count by sin^2 + cos^2 = 1, thus
flexing the floating point unit (FPU).
- In this task, every second the FPU
save/restore flag is alternately set and cleared. When cleared, the
FPU registers are not saved, thus rendering all Linux process
floating-point calculations useless.
- A companion process to this
task runs a big sum computation and shows what the effect of bad FPU
context looks like: terrible floating-point results for one second,
good ones for the next second, etc.:
...
50000005000000.000000
50000005000000.000000
...
nan
nan
nan
...
50000005000000.000000
50000005000000.000000
...
The 'nan' here means "not a number," that is, the floating point value
is junk that does not conform to the IEEE floating point
specification.
- Note that when you run the demo, you may get good output all the
time. It depends on the vagaries of when the Linux and RT tasks
execute. Don't assume that if this demo shows good output, you don't
need to call the aforementioned functions.
Running the Demo
To run the demo, change to the 'ex12_math' 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 "Floating Point" button.
You'll see diagnostics messages printing out.
See the Real-Time Task Code
See the Linux Application Code
Next: Acknowledgements
Back: Example 11, Measuring Timing
Jitter