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