RTAI Parallel Port Interrupt LXRT Example (RTAI3.2) Standalone Version:
A user-space (LXRT) hard real time example for capturing the parallel port interrupt.
This example is derived from Parallel Port Interrupt LXRT Example (RTAI3.0r4 or RTAI3.1)
and Parallel Port Interrupt LXRT Example (RTAI3.2), but it does not need any additional
stimulus of the parallel port interrupt pin. There is another real time task, which generates a square wave on all output
pins.
Also see: Parallel Port Interrupt LXRT Example for RTAI 3.1 - Standalone (with a square wave realtime task)
RTAI/fusion Parallel Port Interrupt ISR - Standalone version (with a square wave realtime task)
Bugfix 10-MAY-2005: Make sure you do any nano2count after the real time timer has been started!
rt_set_oneshot_mode();
start_rt_timer(0);
period = nano2count(PERIOD);
rt_make_hard_real_time();
It also can be used as template for writing or reading to/from the parallel port in certain intervals.
I.e. write to the parallel port to start the AD conversion - the interrupt service routine (ISR) is triggered when
the analog digital converter is ready, the ISR reads the value and does something with it ;-)
Compile "parlxrtmagma.c" with "make".
Make a "null-modem" for the parallel port - connect any output pin (pin 2-9) with
the IRQ pin (pin 10 = ACK).
Load the RTAI kernel modules with "loadmods.sh"
Start "parlxrtmagma" in one shell and you'll see the detected interrupts:
muon:/home/rtai/parlxrtmagma2# ./parlxrtmagma
GIVE THE NUMBER OF INTERRUPTS YOU WANT TO COUNT: 3
RETVAL 0, OVERRUNS 0, INTERRUPT COUNT 1
RETVAL 0, OVERRUNS 0, INTERRUPT COUNT 2
RETVAL 0, OVERRUNS 0, INTERRUPT COUNT 3
TEST ENDS
Developed and tested on kernel 2.6.10 / RTAI3.2
Example "parlxrtmagma.c" (RTAI LXRT hard real time)
/* RTAI LXRT Parallel Port Interrupt - www.captain.at
This example is for RTAI3.2
Based on usi_process.c from showroom
Needs a "null-modem" for the parallel port:
connect any output pin (pin 2-9) with the IRQ pin (pin 10 = ACK).
*/
#include <stdio.h>
#include <errno.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <unistd.h>
#include <rtai_lxrt.h>
#include <rtai_sem.h>
#include <rtai_usi.h>
#include <sys/io.h>
#define PARPORT_IRQ 7
#define BASEPORT 0x378
static SEM *dspsem;
static volatile int end = 1;
static volatile int endsquare = 1;
static volatile int ovr, intcnt, retval, maxcnt;
#define PERIOD 1000000000
static void *timer_handler(void *args)
{
RT_TASK *handler;
if (!(handler = rt_task_init_schmod(nam2num("HANDLR"), 0, 0, 0, SCHED_FIFO, 0xF))) {
printf("CANNOT INIT HANDLER TASK > HANDLR <\n");
exit(1);
}
rt_allow_nonroot_hrt();
mlockall(MCL_CURRENT | MCL_FUTURE);
rt_make_hard_real_time();
end = 0;
rt_request_irq_task(PARPORT_IRQ, handler, RT_IRQ_TASK, 1);
rt_startup_irq(PARPORT_IRQ);
rt_enable_irq(PARPORT_IRQ);
while ( !end && (ovr != RT_IRQ_TASK_ERR) ) {
do {
ovr = rt_irq_wait(PARPORT_IRQ);
if (ovr == RT_IRQ_TASK_ERR) break;
if (end) break;
if (ovr > 0) {
// overrun processing, if any, goes here
rt_sem_signal(dspsem);
}
/* normal processing goes here */
intcnt++;
rt_sem_signal(dspsem); // notify main()
rt_ack_irq(PARPORT_IRQ);
} while (ovr > 0);
rt_pend_linux_irq(PARPORT_IRQ);
}
rt_release_irq_task(PARPORT_IRQ);
rt_make_soft_real_time();
rt_task_delete(handler);
intcnt = maxcnt;
return 0;
}
static void *square_handler(void *args)
{
RT_TASK *handler;
RTIME period;
if (!(handler = rt_task_init_schmod(nam2num("SQHDLR"), 0, 0, 0, SCHED_FIFO, 0xF))) {
printf("CANNOT INIT HANDLER TASK > SQHDLR <\n");
exit(1);
}
rt_allow_nonroot_hrt();
mlockall(MCL_CURRENT | MCL_FUTURE);
rt_set_oneshot_mode();
start_rt_timer(0);
period = nano2count(PERIOD);
rt_make_hard_real_time();
endsquare = 0;
rt_task_make_periodic(handler, rt_get_time() + period, period);
while ( !endsquare ) {
outb_p(0, BASEPORT);
rt_task_wait_period();
outb_p(255, BASEPORT);
rt_task_wait_period();
}
stop_rt_timer();
rt_make_soft_real_time();
rt_task_delete(handler);
intcnt = maxcnt;
return 0;
}
int main(void)
{
RT_TASK *maint; //, *squaretask;
int thread, squarethread;
printf("GIVE THE NUMBER OF INTERRUPTS YOU WANT TO COUNT: ");
scanf("%d", &maxcnt);
if (!(maint = rt_task_init(nam2num("MAIN"), 1, 0, 0))) {
printf("CANNOT INIT MAIN TASK > MAIN <\n");
exit(1);
}
// create semaphore to notify main() when interrupt occurs
if (!(dspsem = rt_sem_init(nam2num("DSPSEM"), 0))) {
printf("CANNOT INIT SEMAPHORE > DSPSEM <\n");
exit(1);
}
// ask for permission to access the parallel port from user-space
if (iopl(3)) {
printf("iopl err\n");
rt_task_delete(maint);
rt_sem_delete(dspsem);
exit(1);
}
outb_p(0x10, BASEPORT + 2); //set port to interrupt mode; pins are output
thread = rt_thread_create(timer_handler, NULL, 10000); // create thread
while (end) { // wait until thread went to hard real time
usleep(100000);
}
squarethread = rt_thread_create(square_handler, NULL, 10000); // create thread
while (endsquare) { // wait until thread went to hard real time
usleep(100000);
}
while (intcnt < maxcnt) {
rt_sem_wait(dspsem);
printf("RETVAL %d, OVERRUNS %d, INTERRUPT COUNT %d\n", retval, ovr, intcnt);
}
end = 1;
endsquare = 1;
printf("TEST ENDS\n");
outb_p(0, BASEPORT);
outb_p(255, BASEPORT); // generate final interrupt to unblock rt_irq_wait
outb_p(0, BASEPORT);
rt_release_irq_task(PARPORT_IRQ);
rt_thread_join(thread);
rt_thread_join(squarethread);
rt_task_delete(maint);
rt_sem_delete(dspsem);
return 0;
}
Makefile for parlxrtmagma.c:
prefix := $(shell rtai-config --prefix)
ifeq ($(prefix),)
$(error Please add <rtai-install>/bin to your PATH variable)
endif
CC = $(shell rtai-config --cc)
LXRT_CFLAGS = $(shell rtai-config --lxrt-cflags)
LXRT_LDFLAGS = $(shell rtai-config --lxrt-ldflags)
all: parlxrtmagma
parlxrtmagma: parlxrtmagma.c
$(CC) $(LXRT_CFLAGS) -o $@ $< $(LXRT_LDFLAGS)
clean:
rm -f *.o parlxrtmagma
.PHONY: clean
Insert the modules with "loadmods.sh":
#!/bin/sh
TMP=$PWD
cd /usr/realtime/modules/
KERNELVERSION=`uname -r | awk '{print substr($1,1,3)}'`
if [ "$KERNELVERSION" = "2.6" ]
then
insmod ./rtai_hal.ko
insmod ./rtai_lxrt.ko
insmod ./rtai_sem.ko
insmod ./rtai_tasklets.ko
insmod ./rtai_usi.ko
cd $TMP
else
insmod ./rtai_hal.o
insmod ./rtai_lxrt.o
insmod ./rtai_sem.o
insmod ./rtai_tasklets.o
insmod ./rtai_usi.o
cd $TMP
fi
Remove the modules with "rmmods.sh":
#!/bin/sh
rmmod rtai_usi
rmmod rtai_tasklets
rmmod rtai_sem
rmmod rtai_lxrt
rmmod rtai_hal
Last-Modified: Sat, 04 Feb 2006 16:13:54 GMT