Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 21 Nov 2007 12:43:49 +0100
From:      "Daan Vreeken [PA4DAN]" <Danovitsch@vitsch.net>
To:        Michiel Overtoom <michiel@motoom.org>
Cc:        freebsd-hackers@freebsd.org
Subject:   Re: Hooking a kernelmodule-function into a timer interrupt
Message-ID:  <200711211243.49878.Danovitsch@vitsch.net>
In-Reply-To: <200711200051.45420.michiel@motoom.org>
References:  <200711200051.45420.michiel@motoom.org>

next in thread | previous in thread | raw e-mail | index | archive | help
Hi Michiel,

On Tuesday 20 November 2007 00:51:45 Michiel Overtoom wrote:
> I'm interfacing an analog-digital converter to the parallel port and I'm
> able to make it work from userland using the ppio driver.  But now I want
> to move the conversion software into a loadable kernel module, and have the
> conversion routine called many times per second, for example 1000 times per
> second.  If would be nice if it gets called at the kern.clockrate.  I have
> no clear idea how to proceed, I suspect I have to install a pointer to my
> conversion function into some list of functions which get called each clock
> tick, but I don't know where, or how. Any tips would be very welcome.
>
> Some more background info: the chip is a ADC08031, hooked up directly to
> some input and output pins on the parallel port. The ADC has a serial
> output, and I use one pin on the parport to clock it. I want to have the
> clocking code executed in some low level timer interrupt handler. I
> inserted some test code into 'hardclock()' in 'kern_clock.c' to toggle a
> bit on the parport, which worked nicely: it got called 1000 times per
> second, which I could actually verify with a frequency meter hooked up to
> the parport; but stuffing the conversion software directly into
> kern_clock.c would not be an elegant solution.

Next you're going to tell us you desperately need the FPU in your control 
loop ;-)

I have done exactly the same as you propose some time ago, but I'm using a 
(Humusoft) PCI board with ADCs/DACs. To be able to load control loops from a 
kernel module I've done the following :

In kern/kern_clock.c I've added :
typedef void (*control_loop_t)(void *arg);
static void		*control_arg;
static control_loop_t	control_loop = NULL;

And later on inside hardclock() I've added :
	if (control_loop != NULL) {
		control_loop(control_arg);
	}

This gives you a variable "control_loop" and "control_arg" that you can fill 
in from your kernel module. "control_arg" is an optional argument that gets 
passed to the function. I use it to transfer a pointer to my driver's softc 
structure to the control loop.

In the kernel module you define :
typedef void (*control_loop_t)(void *arg);
extern void		*control_arg;
extern control_loop_t	control_loop;

Then in your attach or module load function your attach your control 
function :
	control_arg = sc;
	control_loop = &loop_func;

Make sure you fill in the argument first as your function could be called the 
very instruction after you fill in the function pointer.

On detach or module unload you simply disable your control loop with :
	control_loop = NULL;

My control function looks like this :
void loop_func(void *arg)
{
	struct softc	*card = (struct softc *)arg;

	// do something usefull
}


ps: Suc6 met software schrijven ;-)

-- 
Daan



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200711211243.49878.Danovitsch>