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 LXRT Parallel Port Interrupt FIFO Stress Test

This is a simple stress test for RTAI (LXRT user space hard real time). It uses the parallel port to generate interrupts - in the interrupt service routine (ISR) for the parallel port, the time (rt_get_time_ns) is written to a FIFO. The soft real time part in main() calculates the time to the unixtime in nano seconds and writes it into files in the directory data/ . The files are rotated, that we have handy small files with "data".


Compile it with the "Makefile", load the RTAI modules with "./loadmods.sh" and run "./stresstest". In another shell go into the data-directory and check the files generated. This examples needs a "null-modem" for the parallel port: connect any output pin (pin 2-9) with the IRQ pin (pin 10 = ACK).

Developed on RTAI3.3-test2 with ipipe-patched kernels 2.4.32 and 2.6.14.3. Patches supplied in the RTAI tarball. Also tested on RTAI 3.4 (volcano CVS after test1 was released)

stresstest.c
/* RTAI LXRT Parallel Port Interrupt FIFO Stress Test - www.captain.at
	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 <signal.h>

#include <rtai_lxrt.h>
#include <rtai_sem.h>
#include <rtai_usi.h>
#include <rtai_fifos.h>
#include <time.h>

#include <sys/io.h>

#define PARPORT_IRQ  7
#define BASEPORT 0x378
RT_TASK *maint;
int thread, squarethread;
int fd;

static volatile int end = 1;
static volatile int endsquare = 1;
static volatile int ovr, intcnt;
static RTIME start_time_ns;

//              --s-ms-us-ns
#define PERIOD        500000

int timer_handler_has_ended = 0;
int square_handler_has_ended = 0;

static void *timer_handler(void *args)
{
	RT_TASK *handler;
	static RTIME unixtime;
	int muonfifo;
	start_time_ns = rt_get_time_ns();
 	if (!(handler = rt_task_init_schmod(nam2num("HANDLR"), 
 	      0, 0, 0, SCHED_FIFO, 0xF))) {
		printf("CANNOT INIT HANDLER TASK > HANDLR <\n");
		exit(1);
	}

	rtf_create(0, 2000);
	muonfifo = 0;
	rt_allow_nonroot_hrt();
	// no swapping
	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);
			unixtime = rt_get_time_ns();
			rtf_put(muonfifo, &unixtime, sizeof(unixtime) );
			if (ovr == RT_IRQ_TASK_ERR) break;
			if (end) break;
			if (ovr > 0) {
				// overrun processing, if any, goes here 
			}
			intcnt++;
			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);
	rtf_destroy(muonfifo);
   timer_handler_has_ended = 1;
	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();
	// no swapping
	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);
	rt_task_wait_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);
	square_handler_has_ended = 1;
	return 0;
}

void cleanup(int sig) {
	endsquare = 1;
	end = 1;
	return;
}

int main(void) {
	int muonfifo;
	static RTIME unixtime2, currenttime;
	int len;
	char writestr[32];
	char tfn[20];
	time_t captime;
	time_t newtime;
	
	signal(SIGTERM, cleanup);
	signal(SIGINT, cleanup);
	signal(SIGKILL, cleanup);
	
	fd = open("data/outfile", O_RDWR | O_CREAT, 0600);
	if( fd == -1) {
		printf("open error...\n");
		exit(0);
	}
	if ((muonfifo = rtf_open_sized("/dev/rtf0", O_RDWR, 2000)) < 0) {
		printf("ERROR OPENING FIFO0\n");
		exit(1);
	}
	if (!(maint = rt_task_init(nam2num("MAIN"), 1, 0, 0))) {
		printf("CANNOT INIT MAIN TASK > MAIN <\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);
		exit(1);
	}
	//set port to interrupt mode; pins are output
	outb_p(0x10, BASEPORT + 2);
	captime = time(NULL);
	// create thread
	thread = rt_thread_create(timer_handler, NULL, 10000);
	while (end) {   // wait until thread went to hard real time
		usleep(100000);
	}
	squarethread = rt_thread_create(square_handler, NULL, 10000);
	while (endsquare) {   // wait until thread went to hard real time
		usleep(100000);
	}
	while ( read(muonfifo, &unixtime2, sizeof(unixtime2)) > 0 ) {
		currenttime = (RTIME)captime * 1000000000llu + (unixtime2 - start_time_ns);
		len = sprintf(writestr, "%lld\n", currenttime);
		write(fd, writestr, len);
		newtime =  time(NULL);
		if ((newtime - captime) > 90) {
			printf("time=%d\n", (int)newtime);
			sync();						
			close(fd);
			sprintf(tfn, "data/d-%d", (int)newtime);
			fd = open(tfn, O_RDWR | O_CREAT, 0600);
			captime = time(NULL);
			if( fd == -1) {
				printf("ROTATION ERROR\n");
				break;
			}
		}
		if (end == 1) { break; }
	}
	printf("SHUTTING DOWN\n");
	outb_p(0, BASEPORT);
	// generate final interrupt to unblock rt_irq_wait
	outb_p(255, BASEPORT);
	outb_p(0, BASEPORT);

	rt_release_irq_task(PARPORT_IRQ);
	rt_thread_join(thread);
	rt_thread_join(squarethread);
	close(fd);
	rt_task_delete(maint);
  	return 0;
}



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 --lxrt-cflags)
LXRT_LDFLAGS = $(shell rtai-config --lxrt-ldflags)

all:: stresstest

stresstest: stresstest.c
	$(CC) $(LXRT_CFLAGS) -o $@ $< $(LXRT_LDFLAGS) -llxrt
	rm -R -f data
	mkdir data

clean::
	$(RM) -f stresstest

.PHONY: clean

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_usi.ko
insmod ./rtai_fifos.ko
cd $TMP

else

insmod ./rtai_hal.o
insmod ./rtai_lxrt.o
insmod ./rtai_usi.o
insmod ./rtai_fifos.o
cd $TMP

fi



Last-Modified: Thu, 27 Jul 2006 19:21:26 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