Parallel port frequency test of RTAI - Hard real time test
These examples are a demonstration for hard real time.
Compile both examples, hook up a frequency counter on any data pin (pin 2-9) at the parallel port (0x378)
and run "start.sh". See what frequency you're getting with the real time kernel module
(should be 10kHz). In another shell do something CPU intensive like updatedb or compiling
something big. You will see that the frequency stays a 10kHz.
Issue ./stop.sh and run "rect". See again what frequency you're getting (about 1kHz in my case)
and then do something CPU intensive. You will see that the frequency drops and jumps around,
depending on the current CPU load.
Tested on kernel 2.6.7 and vesuvio (hal6c1-2.6.7.patch) on Fedora Core 2 and
kernel 2.4.25 and rtai-3.0r4 on debian sarge (testing release)
myrt_process.c - our kernel module
#include <linux/module.h>
#include <rtai.h>
#include <rtai_sched.h>
#define TICK_PERIOD 50000
#define TASK_PRIORITY 1
#define STACK_SIZE 10000
#define BASEPORT 0x378
static RT_TASK rt_task;
static RTIME tick_period;
static void fun(int t)
{
while (1) {
outb(0, BASEPORT);
rt_task_wait_period();
outb(255, BASEPORT);
rt_task_wait_period();
}
}
int xinit_module(void)
{
outb(0, BASEPORT + 2); //set port to output mode
//RTIME tick_period;
rt_set_periodic_mode();
rt_task_init(&rt_task, fun, 1, STACK_SIZE, TASK_PRIORITY, 1, 0);
tick_period = start_rt_timer(nano2count(TICK_PERIOD));
rt_task_make_periodic(&rt_task, rt_get_time() + tick_period, tick_period);
return 0;
}
void xcleanup_module(void)
{
stop_rt_timer();
rt_task_delete(&rt_task);
return;
}
module_init(xinit_module);
module_exit(xcleanup_module);
MODULE_LICENSE("GPL");
Makefile for the kernel module (kernel 2.6)
obj-m := myrt_process.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
EXTRA_CFLAGS := -I/usr/realtime/include -I/usr/include/
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
Makefile for the kernel module (kernel 2.4)
TARGET := myrt_process
INCLUDE := -I/lib/modules/`uname -r`/build/include -I/usr/realtime/include
CFLAGS := -O2 -Wall -DMODULE -D__KERNEL__ -DLINUX
CC := gcc
${TARGET}.o: ${TARGET}.c
$(CC) $(CFLAGS) ${INCLUDE} -c ${TARGET}.c
start.sh to insert the modules and start our kernel module (for kernel 2.6)
#!/bin/sh
TMP=$PWD
cd /usr/realtime/modules/
insmod ./rtai_hal.ko
insmod ./rtai_ksched.ko
cd $TMP
insmod ./myrt_process.ko
start.sh for kernel 2.4
#!/bin/sh
TMP=$PWD
cd /usr/realtime/modules/
insmod rtai_hal.o
insmod rtai_ksched.o
cd $TMP
insmod myrt_process.o
stop.sh to remove the modules
#!/bin/sh
rmmod myrt_process
rmmod rtai_up
rmmod rtai_ksched
rmmod rtai_hal
(on kernel 2.6 rtai_up is listed via "lsmod"; on kernel 2.4 it is rtai_ksched, so we try to remove both)
User-space test rect.c:
call updatedb or something CPU intensive to see the frequency changing on the parallel port
Compile with: # gcc -O2 -o rect rect.c
#include <stdio.h>
#include <stdlib.h>
#include <asm/io.h>
#include <signal.h>
#define BASEPORT 0x378
static int end;
static void endme(int dummy)
{
end=1;
}
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 ;-)
// 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);
}
signal(SIGINT, endme);
outb(0, BASEPORT + 2); // set to output mode
while (!end) { // adjust usleep if you want
usleep(0);
outb(0, BASEPORT);
//usleep(0);
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");
}
}
Last-Modified: Sat, 04 Feb 2006 16:13:49 GMT