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) Standalone Version:

A user-space (LXRT) hard real time example for capturing the parallel port interrupt.
This example is derived from Parallel Port Interrupt LXRT Example (RTAI3.0r4 or RTAI3.1) and Parallel Port Interrupt LXRT Example (RTAI3.2), but it does not need any additional stimulus of the parallel port interrupt pin. There is another real time task, which generates a square wave on all output pins.

Also see: 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)

Bugfix 10-MAY-2005: Make sure you do any nano2count after the real time timer has been started!
	rt_set_oneshot_mode();
	start_rt_timer(0);
 	period = nano2count(PERIOD);
 	rt_make_hard_real_time();

It also can be used as template for writing or reading to/from the parallel port in certain intervals. 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 "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 you'll see the detected interrupts:
muon:/home/rtai/parlxrtmagma2# ./parlxrtmagma
GIVE THE NUMBER OF INTERRUPTS YOU WANT TO COUNT: 3
RETVAL 0, OVERRUNS 0, INTERRUPT COUNT 1
RETVAL 0, OVERRUNS 0, INTERRUPT COUNT 2
RETVAL 0, OVERRUNS 0, INTERRUPT COUNT 3
TEST ENDS

Developed and tested on kernel 2.6.10 / RTAI3.2



Example "parlxrtmagma.c" (RTAI LXRT hard real time)
/* RTAI LXRT Parallel Port Interrupt - www.captain.at
	This example is for RTAI3.2
	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 endsquare = 1;
static volatile int ovr, intcnt, retval, maxcnt;

#define PERIOD 1000000000

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

static void *square_handler(void *args)
{
	RT_TASK *handler;
	RTIME period;

 	if (!(handler = rt_task_init_schmod(nam2num("SQHDLR"), 0, 0, 0, SCHED_FIFO, 0xF))) {
		printf("CANNOT INIT HANDLER TASK > SQHDLR <\n");
		exit(1);
	}
	rt_allow_nonroot_hrt();
	mlockall(MCL_CURRENT | MCL_FUTURE);

	rt_set_oneshot_mode();
	start_rt_timer(0);
 	period = nano2count(PERIOD);
	rt_make_hard_real_time();
	endsquare = 0;
	rt_task_make_periodic(handler, rt_get_time() + period, period);

	while ( !endsquare ) {
		outb_p(0, BASEPORT);
		rt_task_wait_period();
		outb_p(255, BASEPORT);
		rt_task_wait_period();
	}

	stop_rt_timer();
	rt_make_soft_real_time();
	rt_task_delete(handler);
	intcnt = maxcnt;
	return 0;
}


int main(void)
{
	RT_TASK *maint; //, *squaretask;
	int thread, squarethread;
	
	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);
	}
	
	squarethread = rt_thread_create(square_handler, NULL, 10000);  // create thread
	while (endsquare) {   // 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;
	endsquare = 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_thread_join(squarethread);
	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":
#!/bin/sh
TMP=$PWD
cd /usr/realtime/modules/

KERNELVERSION=`uname -r | awk '{print substr($1,1,3)}'`

if [ "$KERNELVERSION" = "2.6" ]
then

insmod ./rtai_hal.ko
insmod ./rtai_lxrt.ko
insmod ./rtai_sem.ko
insmod ./rtai_tasklets.ko
insmod ./rtai_usi.ko
cd $TMP

else

insmod ./rtai_hal.o
insmod ./rtai_lxrt.o
insmod ./rtai_sem.o
insmod ./rtai_tasklets.o
insmod ./rtai_usi.o
cd $TMP

fi
Remove the modules with "rmmods.sh":
#!/bin/sh
rmmod rtai_usi
rmmod rtai_tasklets
rmmod rtai_sem
rmmod rtai_lxrt
rmmod rtai_hal


Last-Modified: Sat, 04 Feb 2006 16:13:54 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