Floating point in interrupt handler
Daan Vreeken [PA4DAN]
Danovitsch at vitsch.net
Mon Oct 22 13:00:38 PDT 2007
Hi all,
For a work related project I'm trying to create a sort of real-time control
loop. I've written a driver for a PCI data acquisition card that features a
number of digital-to-analog and analog-to-digital converters. The goal is to
create a control loop that runs about 10000 times a second and can be altered
on the fly. The control loop should always run, running the rest of FreeBSD
(kernel and userland) is less important.
To achieve this I've been playing with some modifications to hardclock(). I
have added hooks to hardclock() that will call my external loop function once
attached. The loop function lives in a seperate kernel module that can be
loaded and unloaded on the fly. After changing HZ to 10000 I now have a
function that gets called 10000 times a second that can manipulate the
outputs of the acquisition board.
As a first test I've created a simple loop that uses integer arithmetic and a
lookup table to create a sine wave on one of the DAC outputs. This works like
a charm, but I really would like to be able to use floating point
instructions to create more advanced control loops.
So I've added asm inline functions to use the FPU's fsin and fcos operands. At
the start of my loop function I (try to) save the FPU state with the
following code :
td = curthread;
npxgetregs(td, &fpu_state);
At the end of the function I restore the FPU state with :
npxsetregs(td, &fpu_state);
In between I currently have :
// create a 500Hz sine wave, modulate it with a 2Hz sine wave and
// let it have a 10.0 Volt amplitude
t += 0.0001;
set_dac_voltage(card, 0,
fp_sin(500 * 2 * M_PI * t) * fp_sin(2 * 2 * M_PI * t) * 10.0);
As uggly as the code may seem, it works and the output of the acquisition
board shows the expected signal on a scope. While the code seems to do what
it should, the kernel floods the console with the following message :
kernel trap 22 with interrupts disabled
As I'm completely new to saving/restoring the FPU state and working with it
from within the kernel (and especially from within an interrupt handler) I'm
not sure if all the above is the correct way to do things, so please correct
me if I'm doing things wrong.
I'm also not sure if the FPU state is correctly restored and I haven't done
any tests (yet) to check this, but judging by the amount of trap-22 messages
I'm getting, I must be doing something wrong ;-)
I have done some Googling and found a couple of interresting threads to read :
http://unix.derkeiler.com/Mailing-Lists/FreeBSD/hackers/2007-03/msg00096.html
http://lists.freebsd.org/pipermail/freebsd-emulation/2007-April/003448.html
But what I haven't found is a description of exactly what the kernel is
missing to allow floating point operations to be done there. Can anyone tell
if I'm saving/restoring the FPU state the right way in the code snippets
above and what I should do to correctly stop trap 22 from occuring?
Thanks,
--
Daan
More information about the freebsd-hackers
mailing list