UPDATE: Click here if you have problems with the parallel port interrupt
Parallel Port Interrupt Kernel Module Examples - Simple Device Driver:
Two kernel modules for capturing the parallel port interrupt.
First one "parlat.c" measures the parallel port interrupt latency with RTAI (real-time linux).
Simple make a "null-modem" for the parallel port - connect any output pin (pin 2-9) with
the IRQ pin (pin 10 = ACK). Compile the parlat module and insert it. Check the kernel log
file for the generated messages.
The second example shows how to handle the par port int without hard real time - in soft real time.
Developed on kernel 2.4.25 / RTAI3.0r4 and kernel 2.6.8.1 / RTAI3.1 with gcc 3.3.4
Also tested on kernel 2.6.10 / RTAI 3.2 with gcc 2.95.4.
Note: Just ignore warnings like: *** Warning: "rt_release_irq" [...] undefined!
If the RTAI kernel modules are loaded, the symbols will resolve.
Example "parlat.c" (RTAI hard real time)
#include <linux/module.h>
#include <rtai.h>
#include <rtai_sched.h>
#define BASEPORT 0x378
static int time;
static int time2;
static int timex;
static int timex2;
static void handler(void)
{
int timediff;
time2 = rt_get_time_ns();
timex2 = rt_get_cpu_time_ns();
timediff = time2 - time;
rt_printk(">>> interrupt latency = %d ns\n", timediff);
timediff = timex2 - timex;
rt_printk(">>> interrupt latency = %d ns\n", timediff);
rt_ack_irq(7);
}
int xinit_module(void)
{
int ret;
ret = rt_request_global_irq(7, (void *)handler);
rt_enable_irq(7);
outb_p(0x10, BASEPORT + 2); //set port to interrupt mode; pins are output
rt_printk("Generating interrupt now on all output pins (intr/ACK = pin 10)\n");
//generate interrupt
outb_p(0, BASEPORT);
rt_set_oneshot_mode();
time = rt_get_time_ns();
timex = rt_get_cpu_time_ns();
outb_p(255, BASEPORT);
outb_p(0, BASEPORT);
rt_printk("Interrupt generated. You should see the latency message\n");
return 0;
}
void xcleanup_module(void)
{
rt_printk("Unloading parallel port latency test\n");
rt_disable_irq(7);
rt_free_global_irq(7);
}
module_init(xinit_module);
module_exit(xcleanup_module);
MODULE_LICENSE("GPL");
Makefile for parlat.c: (kernel 2.4)
TARGET := parlat
INCLUDE := -I/lib/modules/`uname -r`/build/include -I/usr/realtime/include
CFLAGS := -O2 -Wall -DMODULE -DUSEFIFO -D__KERNEL__ -DLINUX
CC := gcc
${TARGET}.o: ${TARGET}.c
$(CC) $(CFLAGS) ${INCLUDE} -c ${TARGET}.c
Makefile for parlat.c: (kernel 2.6)
obj-m := parlat.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
EXTRA_CFLAGS := -I/usr/realtime/include -I/usr/include/
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
Insert the modules with: (kernel 2.4)
#!/bin/sh
TMP=$PWD
cd /usr/realtime/modules/
check=`lsmod | grep -c "^rtai_hal"`
if [ $check == 0 ]
then
insmod ./rtai_hal.o
fi
check=`lsmod | grep -c "^rtai_ksched"`
if [ $check == 0 ]
then
insmod ./rtai_ksched.o
fi
cd $TMP
check=`lsmod | grep -c "^rt_process"`
if [ $check == 0 ]
then
insmod ./parlat.o
else
rmmod parlat
insmod ./parlat.o
fi
Insert the modules with: (kernel 2.6)
#!/bin/sh
TMP=$PWD
cd /usr/realtime/modules/
check=`lsmod | grep -c "^rtai_hal"`
if [ $check == 0 ]
then
insmod ./rtai_hal.ko
fi
check=`lsmod | grep -c "^rtai_up"`
if [ $check == 0 ]
then
insmod ./rtai_ksched.ko
fi
cd $TMP
check=`lsmod | grep -c "^rt_process"`
if [ $check == 0 ]
then
insmod ./parlat.ko
else
rmmod parlat
insmod ./parlat.ko
fi
Remove the modules with:
#!/bin/sh
rmmod parlat
rmmod rtai_ksched
#rmmod rtai_up
rmmod rtai_hal
Example "parint.c" (soft real-time):
#include <linux/module.h>
#include <linux/interrupt.h>
#include <asm/io.h>
#define BASEPORT 0x378
static int handler(void)
{
// do stuff
printk(">>> PARALLEL PORT INT HANDLED\n");
return IRQ_HANDLED;
}
int xinit_module(void)
{
int ret;
ret = request_irq(7, handler, SA_INTERRUPT, "parallelport", NULL);
enable_irq(7);
//set port to interrupt mode; pins are output
outb_p(0x10, BASEPORT + 2);
printk("Generating interrupt now on all output pins (intr/ACK = pin 10)\n");
//generate interrupt
outb_p(0, BASEPORT);
outb_p(255, BASEPORT);
outb_p(0, BASEPORT);
printk("Interrupt generated. You should see the handler-message\n");
return 0;
}
void xcleanup_module(void)
{
disable_irq(7);
free_irq(7, NULL);
}
module_init(xinit_module);
module_exit(xcleanup_module);
MODULE_LICENSE("GPL");
Makefile for parint.c: (kernel 2.4)
TARGET := parint
INCLUDE := -I/lib/modules/`uname -r`/build/include
CFLAGS := -O2 -Wall -DMODULE -D__KERNEL__ -DLINUX
CC := gcc
${TARGET}.o: ${TARGET}.c
$(CC) $(CFLAGS) ${INCLUDE} -c ${TARGET}.c
Makefile for parint.c: (kernel 2.6)
obj-m := parint.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
Insert the module with: (kernel 2.4)
# insmod ./parint.o
Insert the module with: (kernel 2.6)
# insmod ./parint.ko
Remove the module with:
# rmmod parint
Last-Modified: Tue, 17 Jun 2008 18:30:08 GMT