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 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

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