RTAI/fusion Parallel Port Interrupt ISR - Standalone version (with a square wave realtime task)
Also see Porting software from RTAI/fusion to Xenomai
A user-space RTAI/fusion hard real time example for capturing the parallel port interrupt.
The real time task "squarewave" generates a square wave on all parallel port data output pins, which triggers the interrupt.
Another task is printing how many interrupts occured. Furthermore the Interrupt Service Routine
writes to a PIPE (equal to a FIFO in RTAI/classic), which is read (blocking read) in "main".
For RTAI/classic versions see: RTAI Parallel Port Interrupt LXRT Example
It also can be used as template for writing or reading to/from the parallel port in certain intervals i.e. for
logging purposes.
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 "parint.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 fusion kernel modules with "loadmods.sh"
Run "parint" (press CTRL-C to end the program) - you'll see an output like this:
# ./parint
start
rt_intr_create=0
Read from pipe: 1
Read from pipe: 2
Read from pipe: 3
3 interrupts occured
Read from pipe: 4
Read from pipe: 5
Read from pipe: 6
6 interrupts occured
Read from pipe: 7
Read from pipe: 8
cleanup
exit
read error
The "read error" is due the fact that the rt_pipe is deleted and then "main" attempts to read from it.
Nothing to worry about in this example, but try to avoid this in real world examples ;-)
parint.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/io.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <rtai/task.h>
#include <rtai/queue.h>
#include <rtai/intr.h>
#include <rtai/pipe.h>
#define STACK_SIZE 8192
#define STD_PRIORITY 1
#define HIGH_PRIORITY 99
#define MID_PRIORITY 50
#define BASEPORT 0x378
#define PARPORTINT 7
#define PIPE_MINOR 0
RT_TASK print_task_ptr;
RT_TASK interrupt_task_ptr;
RT_TASK squarewave_ptr;
RT_INTR intr_desc;
RT_PIPE mypipe;
int int_count = 0;
int end = 0;
int test;
// simple task to count interrupts
void interrupt_task(void *cookie) {
int err = 0;
int error;
error = rt_pipe_create(&mypipe, "intpipe", PIPE_MINOR);
// todo: add error handling
while (!end) {
err = rt_intr_wait(&intr_desc, TM_INFINITE);
if (err > 0) {
int_count++;
rt_pipe_write(&mypipe, &int_count, sizeof(int_count), P_NORMAL);
}
}
rt_pipe_delete(&mypipe);
}
// generates a square wave on the parallel port
void squarewave(void *cookie) {
int i = 0;
rt_task_sleep(1000);
while (!end) {
outb_p(0xff, BASEPORT);
rt_task_sleep(300);
outb_p(0x00, BASEPORT);
rt_task_sleep(300);
}
}
// print out the interrupt-count periodically
void print_task(void *cookie) {
while (!end) {
rt_task_sleep(2300);
printf("%d interrupts occured\n", int_count);
fflush(NULL);
}
}
// signal-handler, to ensure clean exit on Ctrl-C
void clean_exit(int dummy) {
printf("cleanup\n");
end = 1;
rt_intr_delete(&intr_desc);
rt_task_delete(&print_task_ptr);
rt_task_delete(&interrupt_task_ptr);
rt_task_delete(&squarewave_ptr);
printf("exit\n");
}
int main(int argc, char *argv[]) {
int err, fd;
printf("start\n");
// install signal handler
signal(SIGTERM, clean_exit);
signal(SIGINT, clean_exit);
// start timer
rt_timer_start(1000000); // 1ms ticks
// ask for permission to access the parallel port from user-space
if (iopl(3)) {
printf("iopl err\n");
exit(1);
}
// set parallel port to interrupt mode
outb_p(0x10, BASEPORT + 2);
//create interrupt object
err = rt_intr_create(&intr_desc, PARPORTINT, I_AUTOENA);
printf("rt_intr_create=%i\n", err);
rt_intr_enable (&intr_desc);
//spawn some tasks
rt_task_spawn(&print_task_ptr, "Timer",
STACK_SIZE, STD_PRIORITY, 0, &print_task, NULL);
rt_task_spawn(&interrupt_task_ptr, "Interrupt",
STACK_SIZE, HIGH_PRIORITY, 0, &interrupt_task, NULL);
rt_task_spawn(&squarewave_ptr, "OutputTask",
STACK_SIZE, MID_PRIORITY, 0, &squarewave, NULL);
fd = open("/dev/rtp0", O_RDONLY);
while (!end) {
err = read(fd, &test, sizeof(test));
if (err == -1) {
printf("read error\n");
} else {
printf("Read from pipe: %d\n", test);
}
}
close(fd);
fflush(NULL);
return 0;
}
loadmods.sh
#!/bin/sh
TMP=$PWD
cd /usr/realtime/modules/
insmod ./rtai_hal.ko
insmod ./rtai_nucleus.ko
insmod ./rtai_native.ko
cd $TMP
Makefile
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 --fusion-cflags)
LXRT_LDFLAGS = $(shell rtai-config --fusion-ldflags)
all: parint
parint: parint.c
$(CC) $(LXRT_CFLAGS) $(LXRT_LDFLAGS) -lrtai -o $@ $<
clean:
rm -f *.o parint
.PHONY: clean
Last-Modified: Sat, 04 Feb 2006 16:06:01 GMT