RTAI Parallel Port Interrupt LXRT Example (RTAI3.2 - MAGMA):
This is the same as Parallel Port Interrupt LXRT Example (RTAI3.0r4 or RTAI3.1), but
modified to compile and run on RTAI 3.2.
Also see:
Parallel Port Interrupt LXRT Example for RTAI 3.2 - Standalone (with a square wave realtime task)
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)
A user-space (LXRT) hard real time example for capturing the parallel port interrupt.
Compile "set.c" and "reset.c" with "makesetreset.sh", 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 generate some interrupts with "gen.sh" in another shell.
muon:/home/rtai/parlxrtmagma# ./parlxrtmagma
GIVE THE NUMBER OF INTERRUPTS YOU WANT TO COUNT: 2
RETVAL 7, OVERRUNS 0, INTERRUPT COUNT 1
RETVAL 7, OVERRUNS 0, INTERRUPT COUNT 2
TEST ENDS
Developed and tested on kernel 2.6.8.1 / RTAI3.2 MAGMA
Example "parlxrtmagma.c" (RTAI LXRT hard real time)
/* RTAI LXRT Parallel Port Interrupt - www.captain.at
This examples is for RTAI3.2 (MAGMA)
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 ovr, intcnt, retval, maxcnt;
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;
}
int main(void)
{
RT_TASK *maint;
int thread;
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);
}
while (intcnt < maxcnt) {
rt_sem_wait(dspsem);
printf("RETVAL %d, OVERRUNS %d, INTERRUPT COUNT %d\n", retval, ovr, intcnt);
}
end = 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_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": (kernel 2.6)
#!/bin/sh
TMP=$PWD
cd /usr/realtime/modules/
insmod ./rtai_hal.ko
insmod ./rtai_lxrt.ko
insmod ./rtai_sem.ko
insmod ./rtai_tasklets.ko
insmod ./rtai_usi.ko
cd $TMP
Remove the modules with "rmmods.sh":
#!/bin/sh
rmmod rtai_usi
rmmod rtai_tasklets
rmmod rtai_sem
rmmod rtai_lxrt
rmmod rtai_hal
"set.c" (set all parallel port pins to HIGH):
#include <stdio.h>
#include <stdlib.h>
#include <asm/io.h>
#include <termios.h>
#include <time.h>
#define BASEPORT 0x378
int main(int argc, char **argv) {
if (ioperm(BASEPORT, 3, 1)) {
// ask for permissions to access the parallel port
// YOU MUST BE ROOT TO ASK FOR THIS SORT OF PERMISSION, so
// don't forget to 'su' yourself ;-)
// we don't want to interfere with other code
// usage of ioperm: BASEPORT ... base address we want to use
// 3 ... the next 3 bytes
// 1 ... we want the permission
perror("ioperm open");
exit(1);
}
outb(0x10, BASEPORT + 2); // set to output mode; interrupt enabled
outb(255, BASEPORT);
freeperm(); // tell the system we do not use the port anymore
exit(0);
}
int freeperm() {
if (ioperm(BASEPORT, 3, 0)) {
// tell the system we do not use the port anymore
// usage of ioperm: BASEPORT ... base address we want to use
// 3 ... the next 3 bytes
// 0 ... free the permission
perror("ioperm close");
}
}
"reset.c" (reset all parallel port pins to LOW):
#include <stdio.h>
#include <stdlib.h>
#include <asm/io.h>
#include <termios.h>
#include <time.h>
#define BASEPORT 0x378
int main(int argc, char **argv) {
if (ioperm(BASEPORT, 3, 1)) {
// ask for permissions to access the parallel port
// YOU MUST BE ROOT TO ASK FOR THIS SORT OF PERMISSION, so
// don't forget to 'su' yourself ;-)
// we don't want to interfere with other code
// usage of ioperm: BASEPORT ... base address we want to use
// 3 ... the next 3 bytes
// 1 ... we want the permission
perror("ioperm open");
exit(1);
}
outb(0x10, BASEPORT + 2); // set to output mode; interrupt enabled
outb(0, BASEPORT);
freeperm(); // tell the system we do not use the port anymore
exit(0);
}
int freeperm() {
if (ioperm(BASEPORT, 3, 0)) {
// tell the system we do not use the port anymore
// usage of ioperm: BASEPORT ... base address we want to use
// 3 ... the next 3 bytes
// 0 ... free the permission
perror("ioperm close");
}
}
Compile set.c and reset.c with "makesetreset.sh":
#!/bin/sh
gcc -O2 -o set set.c
gcc -O2 -o reset reset.c
Use "gen.sh" to generate an interrupt by setting all pins to LOW-HIGH-LOW:
#!/bin/sh
./reset
./set
./reset
Last-Modified: Sat, 04 Feb 2006 16:13:53 GMT