Okay, back to the float/memory problem. I've attached 4 files to this message: one is just a makefile, one is a common header, one is the rt code, the other is user code. When the rt module (rt_daq) is inserted, it essentially does nothing until 'random_table' is run. random_table computes some random numbers, and passes them (via the shared memory) to the rt process. 'sh_mem->table_flag' is used to ensure the two processes are reading/writing to shared_memory at the same time. The number of random numbers computed = RANDOM_ARRAY_SIZE, and is defined at the top of rt_daq.h. if RANDOM_ARRAY_SIZE = 100 -> Everything works fine elseif RANDOM_ARRAY_SIZE = 1000 -> System reboot I recommend not setting RANDOM_ARRAY_SIZE = 1000 unless you enjoy fsck as much as I do. :) Cheers - Chuck On Tue, 11 Apr 2000 [EMAIL PROTECTED] wrote: > > Please send me code. I wonder if it is purely a timing issue and > has something to do with a case when a RT thread runs out of time > while using FP. This would be easy to check. In fact, you could > try the following > rtl_no_interrupts(x) > while(1){ > do floating point > rtl_sched(); /* call the scheduler, don't wait for resched */ > } > > On Tue, Apr 11, 2000 at 01:53:50PM -0400, [EMAIL PROTECTED] wrote: > > I'd like to second David Christini's problem. > > > > Like Pavel, I have various RT applications that use doubles. (I never use > > floats to avoid unnecessary bugs.) I use several math functions, > > specifically: exp(), sin(), cos() and sqrt(); > > > > Like David however, none of my systems are particularly stable. As > > Pavel suggested I think the instability is coming from memory related > > issues, but not the user/kernel type. > > > > All of my modules are stable if I use a 'small' number of doubles, > > and a 'small' number of operations on those doubles (per period in a > > periodic rt thread.) I observe two possibly related phenomena-- > > > > 1) as I increase the number of double operations in a cycle, the cpu will > > eventually lock up. This doesn't concern me, perhaps I'm asking > > too much of it -- > > It works with something like 100 double fxns > > {ie. exp(),sin(),etc.} & 1000 double operations {ie +-*/} > > every 100 microseconds, on a 450MHz PIII. > > > > 2) as I increase the number of doubles I use, the system will eventually > > spontaneously reboot itself. This phenomenon is unpredictable. > > ~100 double variables -> works every time. > > 'every time' = hundreds of trials for up to > > millions of periods per trial. > > ~1000 double variables -> reboots every time. > > ~100->1000 double variables -> works/reboots randomly. > > > > Obviously I observe this when using arrays of doubles, and the > > numbers I listed above are highly dependent on the number of > > operations I perform in a given period. But even if I perform > > almost no operations in a loop (say, only one typecast), an array > > of 2000 doubles in my module will reboot the system upon > > insertion. Understand that for a given operation number, the > > number of stable double variables is a constant. > > > > Two examples: > > 1) 1 array of 100 doubles & 10 other doubles > > ~400 operations & 99 functions > > -works fine every time > > 1 array of 105 doubles & 10 other doubles > > ~400 operations & 99 functions (extra doubles aren't used) > > - reboots every time > > > > 2) 4 arrays of 10 doubles & 30 other doubles > > ~150 operations & 78 functions > > - works fine every time > > 4 arrays of 11 doubles & 30 other doubles > > ~150 operations & 78 functions (extra doubles aren't used) > > - reboots every time > > > > If I use 'int' in place of 'double', (of course I can't use the math > > fxns), but I find arrays of 100,000 members reliable, without any crash > > or reboot. (I assume I could go to millions of members before running into > > a problem.) > > > > After extreme frustration, I gave up pressing this issue about a month > > ago, and just restricted myself to small double arrays. But I suspect that > > my issues are related to David Christini's, so I thought I'd bring it up. > > > > If anyone is interested in examining my problem, > > let me know and I'll send out the code... > > > > Chuck > > > > On Tue, 11 Apr 2000, Pavel Andris wrote: > > > David, > > > I use kernel 2.2.13, RTL 2.0. My RT application uses double variables > > > and operations heavily including sin(), cos(), sqrt(), atan2(). I also > > > use shared memory (Tomek Motylewski's mbuff). I don't remember any > > > crash caused by floating point operations. I'd expect your trouble is > > > caused by something else (float/double confusion?, kernel/user memory > > > context trouble?). > > > Regards, Pavel Andris > > > > -- [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/ > > -- > --------------------------------------------------------- > Victor Yodaiken > FSMLabs: www.fsmlabs.com www.rtlinux.com > FSMLabs is a servicemark and a service of > VJY Associates L.L.C, New Mexico. > > -- [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/ >
## Makefile Hacked from so many places, it's not ## worth my labeling them all -- ADD2 ##### Compiler, Flags, etc. ##### CC = gcc GCC = g++ MOC = moc USR_CFLAGS = -pipe -Wall -O2 -W -g RTL_CFLAGS = -Wall -Wstrict-prototypes -O2 \ -fomit-frame-pointer -fno-strength-reduce RTL_DEFS = -D__RT__ -D__KERNEL__ -DMODULE -c -DMODVERSIONS USR_INCLUDE = -I /usr/src/rtlinux/rtl/include \ -I /usr/src/rtlinux/linux/include \ -I /usr/src/rtlinux/rtl RTL_INCLUDE = -I /usr/src/rtlinux/linux/include \ -I /usr/src/rtlinux/include/posix \ -I /usr/src/rtlinux/include LFLAGS = -L/usr/lib -lqt -L/usr/X11R6/lib -lX11 -lXext -lqwt ##### File Names ##### RTL_HEADER = rt_daq.h RND_SOURCE = random_table.cc RTL_SOURCE = rt_daq.c RND_TARGET = random_table RTL_TEMP = rt_daq_temp.o RTL_TARGET = rt_daq.o ##### Build Rules ##### all: $(RND_TARGET) $(RTL_TEMP) $(RTL_TARGET) daq: $(RTL_TEMP) $(RTL_TARGET) $(RND_TARGET): $(RND_SOURCE) $(RTL_HEADER) $(GCC) $(USR_INCLUDE) $(USR_CFLAGS) $(LFLAGS) \ $(RND_SOURCE) -o $(RND_TARGET) $(RTL_TEMP): $(RTL_SOURCE) $(RTL_HEADER) $(CC) $(RTL_INCLUDE) $(RTL_CFLAGS) $(RTL_DEFS) \ -c $(RTL_SOURCE) -o $(RTL_TEMP) $(RTL_TARGET): $(RTL_TEMP) $(CC) -nostdlib -static -r $(RTL_TEMP) \ -o $(RTL_TARGET) -lgcc -lm
// Known Headers #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <sys/mman.h> #include <math.h> #include "rt_daq.h" #define TWO_PI 6.28318530717958647692 // pi * 2 SHARED_MEM_STRUCT *sh_mem; // pointer to shared memory int fd_shared_mem; // This is a KEY function!!! Does math! int main() { int i, j, N; j = 0; N = RANDOM_ARRAY_SIZE; srand(0); // Open memory address pointer if ((fd_shared_mem = open("/dev/mem", O_RDWR)) < 0) { fprintf(stderr, "Error opening /dev/mem \n"); exit(1); } sh_mem =(SHARED_MEM_STRUCT *)mmap(0,sizeof(SHARED_MEM_STRUCT), PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, fd_shared_mem, SHARED_MEM_ADDRESS); // Write Math Table to rt memory via shared memory while(sh_mem->table_flag != TABLE_FULL) { if(sh_mem->table_flag == TABLE_WRITE) { for(i=0;i<SHARED_ARRAY_SIZE;i++) { sh_mem->cos_rand[i] = cos ( TWO_PI * (double)rand() / (double)RAND_MAX ); sh_mem->log_rand[i] = log ( (double)rand() / (double)RAND_MAX ); } j+=SHARED_ARRAY_SIZE; printf("%d of %d entries complete\n",j,N); sh_mem->table_flag = TABLE_READ; } } printf("Random number table created with %d values.\n", RANDOM_ARRAY_SIZE); munmap((char *)sh_mem, sizeof(SHARED_MEM_STRUCT)); return(0); }
#ifndef __RT_DAQ_H #define __RT_DAQ_H // Basics #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif // MAKE THIS NUMBER BIG -> KABOOM!!!! #define RANDOM_ARRAY_SIZE 100 // max number rands #define SHARED_ARRAY_SIZE 10 // System/needs dependent #define HZ_FREQUENCY 10000 //RT Task frequency #define T_MS .1 // 1000/HZ_FREQUENCY #define SHARED_MEM_ADDRESS (126*0x100000) //Setup /etc/lilo.conf // Error Values for the functions listed #define THREAD_NOT_INITIALIZED 601 // pthread_create #define THREAD_NOT_FLOAT 602 // pthread_setfp_np #define THREAD_NOT_PERIODIC 603 // pthread_make_periodic_np #define THREAD_NOT_DESTROYED 604 // pthread_delete_np #define ATTR_NOT_INITIALIZED 610 // pthread_attr_init #define SETSCHED_NOT_MODIFIED 611 // pthread_attr_setschedparam #define TABLE_FULL 102 // proceed with periodic thread #define TABLE_READ 103 // rt pthread waiting #define TABLE_WRITE 104 // usr side waiting // Shared Memory Sturcture, accessed by user & kernel spaces typedef struct { // System Error/Debug int error_type; int error_detail; int table_flag; int data_wait; double cos_rand[SHARED_ARRAY_SIZE]; double log_rand[SHARED_ARRAY_SIZE]; } SHARED_MEM_STRUCT; #endif // __RT_DAQ_H
#include <rtl.h> #include <time.h> #include <pthread.h> #include "rt_daq.h" // ***** Function Declarations *****/ void init_shared_mem(void); // initialize user/kernel memory void *daq_code(void*); // CPU Periodic function // ***** Global Variables ***** // // RT required pthread_t daq_thread; // main rtlinux thread SHARED_MEM_STRUCT *sh_mem; // shared memory: user/kernel // Safety Flags int error_flag; // ***** Functions ***** // // ***** INIT_MODULE, rtLinux standard function // before rt_daq.o, board must be configured see comedi docs int init_module(void) { pthread_attr_t attr; struct sched_param sched_param; hrtime_t now, period, soon; now = clock_gethrtime(CLOCK_REALTIME); period = HRTICKS_PER_SEC / HZ_FREQUENCY; soon = now + (100 * period); // Open shared memory structure, and rt fifos init_shared_mem(); // initialize pthread attributes error_flag = pthread_attr_init(&attr); if(error_flag && !(sh_mem->error_type)) { sh_mem->error_type = ATTR_NOT_INITIALIZED; sh_mem->error_detail = error_flag; } // modify pthread attributes for top priority sched_param.sched_priority = 1; error_flag = pthread_attr_setschedparam(&attr,&sched_param); if(error_flag && !(sh_mem->error_type)) { sh_mem->error_type = SETSCHED_NOT_MODIFIED; sh_mem->error_detail = error_flag; } // initialize the real time cpu thread error_flag = pthread_create(&daq_thread, &attr, daq_code,(void *)1); if(error_flag && !(sh_mem->error_type)) { sh_mem->error_type = THREAD_NOT_INITIALIZED; sh_mem->error_detail = error_flag; } // allow use of floating point numbers error_flag = pthread_setfp_np(daq_thread,TRUE); if(error_flag && !(sh_mem->error_type)) { sh_mem->error_type = THREAD_NOT_FLOAT; sh_mem->error_detail = error_flag; } // make the thread periodic error_flag = pthread_make_periodic_np (daq_thread, soon, period ); if(error_flag && !(sh_mem->error_type)) { sh_mem->error_type = THREAD_NOT_PERIODIC; sh_mem->error_detail = error_flag; } return 0; } // Initialize the rt/linux shared memory void init_shared_mem(void) { //Open Shared Memory structure; '__va' command new in 2.2.x sh_mem = (SHARED_MEM_STRUCT *) __va(SHARED_MEM_ADDRESS); // Initialize flags & error values sh_mem->error_type = 0; sh_mem->error_detail = 0; if(RANDOM_ARRAY_SIZE) sh_mem->table_flag = TABLE_WRITE; else sh_mem->table_flag = TABLE_FULL; } // Task reads/writes data to DAQ board void *daq_code(void *param) { int table_index, i; double cos_rand[RANDOM_ARRAY_SIZE]; double log_rand[RANDOM_ARRAY_SIZE]; table_index = 0; while (1) // periodic task, must loop { pthread_wait_np(); //wait for next period if(sh_mem->table_flag!=TABLE_FULL) { if(sh_mem->table_flag==TABLE_READ) { for(i=0;i<SHARED_ARRAY_SIZE;i++) { cos_rand[table_index] = sh_mem->cos_rand[i]; log_rand[table_index] = sh_mem->log_rand[i]; table_index++; } } if(table_index == RANDOM_ARRAY_SIZE) sh_mem->table_flag = TABLE_FULL; else sh_mem->table_flag = TABLE_WRITE; } else { // Do Nothing for simplicity } } } void cleanup_module(void) { // destroy periodic thread error_flag = pthread_delete_np(daq_thread); if(error_flag && !(sh_mem->error_type)) { sh_mem->error_type = THREAD_NOT_DESTROYED; sh_mem->error_detail = error_flag; } }