Hi everybody!
I am new to rtlinux and the wonderful PC world and I need help!
We are building a new data acquisition sytem and after reading the rtlinux
doc
we designed a two process system, one (real time) to do the actual data
acquisition from
a Real Time Devices DM6420HR board, and the other (linux) to process and
save the data.
The real time task would write its data in a real time fifo and the linux
task would
read it from the same fifo. The rt task should be made periodic (rate of 10
kHz)
by a call to pthread_make_priodic_np. This seemed to be fine. So let's try
it!
To begin, I made a small test system with almost nothing to do (just
checking that we
don't lose data at this rate).
I tried to run a simple real time process (code follows) and its linux
companion
and experienced system crashes. No messages, no warnings, just a sudden
crash followed
(sometimes) by a reboot. rtl_debug didn't helped to find the culprit. The
crash may
happen after a few seconds or several hours!
If I didn't write in the fifo, I experienced no problem. So it seems linked
to the real time fifos.
I tried to run slower at a 1 kHz rate (maybe 10 kHz is to fast)
and had a crash anyway (after 2 days).
I'm running RTlinux 3.0 (beta) on digital PC 3000 (300 mHz).
My questions are:
Did I do something wrong? and what? My example looks so simple and was
inspired
by other examples in
/usr/src/rtlinux/examples
Is it a known bug? I'm running a beta version.
What other means, besides fifos, can be used to transfer data from the
real-time
task to the linux process.
Here is the code:
First the real time process (here with a default task rate of 1 kHz):
#define NDEBUG
#include <rtl.h>
#include <time.h>
#include <pthread.h>
#include <rtl_fifo.h>
#include <rtl_time.h>
#ifndef NDEBUG
#include <rtl_debug.h>
#endif
#ifndef PERIOD
# define PERIOD 1000000 // 1000000 nanoseconds -> 1 kHz
#endif // PERIOD
pthread_t thread;
struct sched_param p;
int overrun = 0;
unsigned long cntr = 0;
void * start_routine(void *arg)
{
#ifndef NDEBUG
breakpoint();
#endif
p.sched_priority = 1;
pthread_setschedparam (pthread_self(), SCHED_FIFO, &p);
pthread_make_periodic_np (pthread_self(), gethrtime() + 5000000000,
PERIOD); /* Task period in nanoseconds */
while (1) {
pthread_wait_np ();
if(overrun++)
{
rtl_printf("Task rate too fast!\n");
}
if(rtf_put(1, (char *)&cntr, sizeof(unsigned long)) < 0)
rtl_printf("Error while writing in RTFIFO\n");
++cntr;
--overrun;
}
return 0;
}
int init_module(void) {
int i;
rtf_destroy(1);
if((i = rtf_create(1, 2000 * sizeof(unsigned long))) < 0)
rtl_printf("Error while creating RTFIFO: %s\n",
i == -(ENODEV) ? "ENODEV" : i == -(ENOMEM) ? "ENOMEM" :
i == -(EBUSY) ? "EBUSY" : "UNKNOWN_CODE");
return pthread_create (&thread, NULL, start_routine, 0);
}
void cleanup_module(void) {
rtf_destroy(1);
pthread_delete_np (thread);
}
Basically, it just sends successive integers to the linux process through
the fifo 1.
And now, the linux process:
//
// This process reads /dev/rtf1 and must receive a continuous stream
// of increasing integer values contained in an unsigned long
//
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <syslog.h>
#include <rtl_fifo.h>
#include <rtl_time.h>
#define MAX_CNT 1000000
time_t tc;
unsigned long cntr;
unsigned long cntr_prec = -1;
FILE *msgf;
int main()
{
int fd1;
int n;
unsigned long i;
if ((fd1 = open("/dev/rtf1", O_RDONLY)) < 0) {
fprintf(stderr, "Error opening /dev/rtf1\n");
exit(1);
}
if ((msgf = fopen("msg_file", "w")) == NULL) {
fprintf(stderr, "Error opening msg_file\n");
exit(2);
}
else
{
tc = time(NULL);
fprintf(msgf, "Start of RTFIFO read application -> %s\n",
ctime(&tc));
fflush(msgf);
}
// for (i = 0; i < MAX_CNT; i++) {
for (i = 0;; ++i) {
n = read(fd1, (void *)&cntr, sizeof(unsigned long));
#if 0
if((i % 1000000) == 0)
{
// Mark time in file
tc = time(NULL);
fprintf(msgf, "-> %s\n", ctime(&tc));
fflush(msgf);
}
#endif
if(n != sizeof(unsigned long))
{
tc = time(NULL);
fprintf(msgf, "%s-> ERROR: %d values read!\n", ctime(&tc),
n);
fflush(msgf);
}
// Check for missed values
if((cntr - cntr_prec) > 1)
{
tc = time(NULL);
fprintf(msgf, "%s-> ERROR at [%lu] : Missed values : Present
[%lu] Previous [%lu]\n" , ctime(&tc), i, cntr, cntr_prec);
fflush(msgf);
}
cntr_prec = cntr;
}
exit( 0);
}
And, finally, the "Makefile":
TASK_PERIOD = 1000000 # Default 1000000 nanoseconds 1 ms
USER_DEFINES = -DPERIOD=$(TASK_PERIOD)
RTL_DIR = /usr/src/rtlinux-3.0
RTLINUX_DIR = /usr/src/rtlinux-3.0/linux
INCLUDE = -I/usr/src/rtlinux-3.0/linux/include \
-I/usr/src/rtlinux-3.0/include \
-I/usr/src/rtlinux-3.0/include/compat
CPP_REQ_DEFINES = \
-DERT -DNUMST=1 \
-DTID01EQ=0 -DUNIX -DMT=0 \
-DMAT_FILE=0 -DINTEGER_CODE=0 \
-DONESTEPFCN=1 -DTERMFCN=1 \
-DHAVESTDIO
CFLAGS = -D__KERNEL__ -Wall -Wstrict-prototypes -fno-strict-aliasing \
-pipe -fno-strength-reduce -m386 -DCPU=386 -g \
-D__RTL__ -DMODULE -D_LOOSE_KERNEL_NAMES -O2 \
-I/usr/src/rtlinux-3.0/linux/include \
-I/usr/src/rtlinux-3.0/include \
-I/usr/src/rtlinux-3.0/include/compat \
-I/usr/src/rtlinux-3.0/include/posix
ARCH = i386
CC = cc
CXXFLAGS = -D__KERNEL__ -Wall -Wstrict-prototypes \
-fno-strict-aliasing -pipe -fno-strength-reduce -m386 \
-DCPU=386 -g -D__RTL__ -DMODULE -D_LOOSE_KERNEL_NAMES \
-fno-exceptions -fno-rtti
all: rt_process.o linux_process
@echo ""
@echo "Built task for a $(TASK_PERIOD) nanoseconds period!"
@echo ""
include ./rtl.mk
linux_process: force
$(CC) $(INCLUDE) $(USER_CFLAGS) -o2 -Wall linux_process.c -o
linux_process
clean:
rm -f *.o
test: all
@echo "Making test at a $(TASK_PERIOD) nanoseconds task period"
@echo "This is the simplest RTLinux program"
@echo "First we remove any existing rtl-modules"
@echo "You may see error warnings from \"make\" - ignore them"
@echo "Type <return> to continue"
@read junk
(./rmrtl)
@echo "Now insert the fifo and scheduler"
@echo "Type <return> to continue"
@read junk
./insrtl
@echo "Now start the real-time tasks module"
@echo "Type <return> to continue"
@read junk
insmod rt_process.o
@echo "Now let's start the application"
@echo "Type <return> to continue"
@read junk
linux_process&
@sleep 3
@echo "Now let's stop the application"
@echo "Type <return> to finish"
@read junk
killall -9 linux_process
rmmod rt_process
rt_process.o: force
force: ;
include $(RTL_DIR)/Rules.make
Timing problems!
----------------
By the way, I tried to measure the "real" period of the task by calling
gethrtime() just after the pthread_wait_np() and comparing the actual time
with
the one saved at the previous passage. I found, for a 100200 nanoseconds
expected period,
measured times of 8512 nanoseconds to 2115168 nanoseconds over a period of
12 hours.
I have read discussions on interrupt jitter and scheduling time error in the
mailing
lists. They are talking of 15 microseconds errors (or even 30). I am far
from that. I know
my values are extreme and the mean error is may be 15 microseconds. Is this
way of measuring
time reliable?
Thanks!
Raymond Roussel ([EMAIL PROTECTED])
============================================================================
===============
Hydro-Quebec Institute of Research [EMAIL PROTECTED]
1800 boulevard Lionel Boulet (514) 652-8329
Varennes Fax: (514) 652-8309
QC
Canada
-- [rtl] ---
To unsubscribe:
echo "unsubscribe rtl" | mail [EMAIL PROTECTED] OR
echo "unsubscribe rtl <Your_email>" | mail [EMAIL PROTECTED]
--
For more information on Real-Time Linux see:
http://www.rtlinux.org/rtlinux/