Captain's Universe Home
Captain's Universe Home
Cosmic Ray Muon DetectorTeleGarden Pages
Time on MarsBryophyllum Plants
Jupiter Radio AstronomyAncient Pages
Salzburg Tourist GuideEarth Magnetometer
  H O M E     AJAX & MORE     LINUX & MORE     RTAI     XENOMAI     ADEOS IPIPE      
    JAVA & BROWSERS     *NIX     ELECTRONICS     REVIEWS     ARTEMIA     FAIRY SHRIMP      


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

Google
 
Web www.captain.at
go to top
© 1996-2010 . All rights reserved.
No reproduction, distribution, publishing or transmission of the copyrighted materials at this site is permitted. Policy
go to top