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/

Reply via email to