Floating point in interrupt handler

Daan Vreeken [PA4DAN] Danovitsch at vitsch.net
Mon Oct 22 13:30:34 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