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      


Xenomai 2.2 Parallel Port Interrupt ISR - Standalone version (with a square wave realtime task)

A user-space Xenomai 2.2 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".


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).
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 <native/task.h>
#include <native/queue.h>
#include <native/intr.h>
#include <native/pipe.h>

#define STACK_SIZE 8192
#define STD_PRIO 1
#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 square_task_ptr;
RT_TASK interrupt_task_ptr;
RT_INTR intr_desc;
RT_PIPE mypipe;
int int_count = 0;
int end = 0;
int test;

//                     --s-ms-us-ns
RTIME task_period_ns =   1000000000llu;
RTIME print_period_ns =  1000000000llu;
RTIME square_period_ns =  300000000llu;

// simple task to count interrupts
void interrupt_task(void *cookie) {
	int err = 0;
	int error;
	error = rt_pipe_create(&mypipe, "intpipe", PIPE_MINOR, 0);
	// 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);
		} else {
			//printf("interrupt_task error = %i\n", err);
		}
		rt_intr_enable (&intr_desc);
	}
	rt_pipe_delete(&mypipe);
}

// print out the interrupt-count periodically
void print_task(void *cookie) {
	unsigned long overrun;
	int ret = rt_task_set_periodic(NULL, TM_NOW, rt_timer_ns2ticks(print_period_ns));
	if (ret) {
		printf("error while set periodic, code %d\n",ret);
		return;
	}
	while (!end) {
		ret = rt_task_wait_period(&overrun);
		if (ret) {
			printf("error while rt_task_wait_period, code %d\n",ret);
			return;
		}
		printf("%d interrupts occured\n", int_count);
		fflush(NULL);
	}
}

// generates a square wave on the parallel port
void squaretask(void *cookie) {
	unsigned long overrun;
	int ret = rt_task_set_periodic(NULL, TM_NOW, rt_timer_ns2ticks(square_period_ns));
	if (ret) {
		printf("error while set periodic, code %d\n",ret);
		return;
	}
	ret = rt_task_wait_period(&overrun);
	if (ret) {
		printf("error while rt_task_wait_period, code %d\n",ret);
		return;
	}
	while (!end) {
		outb_p(0xff, BASEPORT);
		ret = rt_task_wait_period(&overrun);
		if (ret) {
			printf("error while rt_task_wait_period, code %d\n",ret);
			return;
		}
		outb_p(0x00, BASEPORT);
		ret = rt_task_wait_period(&overrun);
		if (ret) {
			printf("error while rt_task_wait_period, code %d\n",ret);
			return;
		}
	}
}

// signal-handler, to ensure clean exit on Ctrl-C
void clean_exit(int dummy) {
	printf("cleanup\n");
	end = 1;
	
	rt_task_delete(&print_task_ptr);
	rt_task_delete(&square_task_ptr);
	rt_task_delete(&interrupt_task_ptr);
	
	rt_intr_delete(&intr_desc);
	rt_pipe_delete(&mypipe);
	printf("end\n");
}

int main(int argc, char *argv[]) {
	int err, fd;
	printf("start\n");

	// install signal handler
	signal(SIGTERM, clean_exit);	
	signal(SIGINT, clean_exit);	

	// 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);

	mlockall(MCL_CURRENT | MCL_FUTURE);

	// CONFIG_XENO_OPT_NATIVE_INTR=y otherwise it fails with ENOSYS (38)
	err = rt_intr_create(&intr_desc, "parint", PARPORTINT, I_NOAUTOENA);
	printf("rt_intr_create=%i\n", err);
	rt_intr_enable (&intr_desc);

	err = rt_task_spawn(&square_task_ptr, "Square", STACK_SIZE, STD_PRIO, 0, 
                         &squaretask, NULL);
	if (err) {
		printf("error rt_task_spawn\n");
		return 0;
	}

	err = rt_task_spawn(&interrupt_task_ptr, "Int", STACK_SIZE, STD_PRIO, 0,
	                      &interrupt_task, NULL);
	if (err) {
		printf("error rt_task_spawn 2\n");
		return 0;
	}

	err = rt_task_spawn(&print_task_ptr, "Printer", STACK_SIZE, STD_PRIO, 0,
                         &print_task, NULL);
	if (err) {
		printf("error rt_task_spawn 3\n");
		return 0;
	}

//pause(); // or read from pipe

	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);
		}
	}

	fflush(NULL);
	return 0;
}



Makefile

TARGET = parint

ifeq ($(XENODIR),)
    XENODIR = /usr/xenomai
endif

XENO_LIB_DIR = $(shell $(XENODIR)/bin/xeno-config --library-dir)

CC     = $(shell $(XENODIR)/bin/xeno-config --cc)
CFLAGS = -g -I $(XENODIR)/include -lpthread -lnative -lrtdm -L $(XENO_LIB_DIR) -Wall -O2

all: $(TARGET)

$(TARGET): $(TARGET).c

clean:
	$(RM) $(TARGET)
Last-Modified: Sun, 23 Jul 2006 20:45:38 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