[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [rtl] Blocking read from FIFO in Linux app?



Hello,

Your code works fine on my machine. Is it only the Ada program that
behaves incorrectly? Perhaps you could come up with a small example that
I could run?

Michael.

j_clifton@aerosimulation.com (j_clifton@aerosimulation.com) wrote:
Content-Description: "cc:Mail Note Part"
> I installed RTLinux 3.0 on Kernel 2.2.18 on a dual processor PIII 500MHz. All I
> need is a 60Hz signal to a Linux app. I originally tried modifying the Kernel Hz
> from 100 to 960 but for some reason there were a tremendous amount of jitter
> whereas 100Hz was fairly stable.
> 
> For my second attempt, I installed RTL 3.0 and cobbled up a pair of programs
> from the examples. In my test program everything is fine and the jitter is quite
> low no matter what I try to peturb it. When I try to use the read in a large Ada
> program it works for a while and then I start getting zero bytes back from the
> FIFO sometimes instead of blocking until the FIFO is non empty. I put in code to
> read the FIFO again if the read returns zero bytes but instead of blocking on
> the FIFO my CPU utilization is 100%.
> 
> I like having the FIFO return a structure which is the tic count and the elapsed
> time from the RDTSC instruction because it allows me to detect frame overruns
> but I could use a semaphore if anyone has a reliable example.
> 
> Jon Clifton
> 
>     
> 

> all: rtlinux_mod.o linux_app
> 
> include ../../rtl.mk
> 
> linux_app: linux_app.c
> 	$(CC) ${USER_CFLAGS} ${INCLUDE} -Wall -O2 -o linux_app linux_app.c
> 
> test: all
> 	@ -/sbin/rmmod rtlinux_mod
> 	(cd ../../; scripts/rmrtl)
> 	(cd ../../; scripts/insrtl)
> 	@/sbin/insmod -v rtlinux_mod.o
> 	@./linux_app
> 
> stop_test:
> 	@ -/sbin/rmmod rtlinux_mod
> 	-/sbin/rmmod rtl_fifo
> 	-/sbin/rmmod rtl_sched
> 	-/sbin/rmmod rtl_time
> 
> clean:
> 	rm -f *.o linux_app
> 
> include $(RTL_DIR)/Rules.make
> 

> #include <unistd.h>
> #include <stdio.h>
> #include <fcntl.h>
> 
> #define NANOSECONDS_PER_TICK (double)((double)1000.00/(double)500.00) 
> int main(){
> 	int fd,count;
> 	int tics=0;
> 	struct { int count; unsigned int d;}D;
> 	double f;
> 	double sum=0.0;
> 	if( (fd = open("/dev/rtf0",O_RDONLY) ) < 0 ){
> 		perror("Can't open fifo");
> 		exit(-1);
> 	}
> 	read(fd,&D,sizeof(D));
> 	count = D.count;
> 	while( (read(fd,&D,sizeof(D))  == sizeof(D))){
> 		f = (double)D.d;
> 		f = ((f) * NANOSECONDS_PER_TICK)/1000;
>                 sum+=f;
> 		tics++;
> 		printf("Delay was %f microseconds, avg=%f, D={%8d, %08x}\n",
> 			f,sum/(double)tics, D.count, D.d);
> 		if(count && (count+1 != D.count))
> 			printf("Dropped a packet at %d ",count);
> 		count = D.count;
> 	}
> 	return 0;
> }
> 

> #include <rtl.h>
> #include <rtl_fifo.h>
> #include <time.h>
> #include <rtl_sched.h>
> #include <rtl_sync.h>
> #include <pthread.h>
> #include <posix/unistd.h>
> 
> #define FRAME_INTERVAL 16695149LL /* fudged 16.67ms */
> #define FIFO_SIZE 4000
> 
> pthread_t thread;
> int fd;
> int stop = 0;
> static void copy_device_data(unsigned int *);
> 
> void *start_routine(void *arg){
> 	struct sched_param p;
> 	struct {int i; unsigned int d; }D = {0,0};
> 
> 	p.sched_priority=1;
> 	pthread_setschedparam (pthread_self(), SCHED_FIFO, &p);
> 	pthread_make_periodic_np (pthread_self(), 
> 		clock_gethrtime(CLOCK_RTL_SCHED),
> 		FRAME_INTERVAL);
> 	copy_device_data(&D.d);
> 
> 	while(!stop){
> 		pthread_wait_np();
> 		copy_device_data(&D.d);
> 		D.i++;
> 		/* ignore write fails, we just drop the data */
> 		write(fd,&D,sizeof(D));
> 	}
> 	return 0;
> }
> int init_module(void){
> 	
> 	rtf_destroy(0);
>         rtf_create(0,FIFO_SIZE);
> 	if ( (fd = open("/dev/rtf0",O_WRONLY | O_NONBLOCK )) < 0)
> 	{
> 		rtl_printf("rtlinux_mod cannot open fifo\n");
> 		rtl_printf("Error number is %d\n",errno);
> 		return -1;
> 	}
> 	return( pthread_create(&thread,NULL,start_routine,0));
> }
> 
> void cleanup_module(void){ 
> 	stop = 1;
> 	close(fd);
> 	rtf_destroy(0);
> 	pthread_delete_np(thread);
> 	return;
> }
> 
> static void copy_device_data(unsigned int *x)
> {
> 	static int last=0;
> 	int d;
> 	rdtscl(d);
> 	*x= (d - last);
> 	last = d;
> 	return;
> }
> 
> 

> #include <fcntl.h>
> #include <stdio.h>
> #include <unistd.h>
> 
> #define CPU_MHz 500.00L
> #define NANOSECONDS_PER_TICK (double)((double)1000.00/(double)CPU_MHz) 
> //#define DEBUG
> 
> int rtl_wait(void) {
>           //(int * tics, double * delta_t){
> 	static int firstpass=1;
> 	static int fd;
> 	static int rtl_count;
> 	static int n=0;
> 	static int nbytes=0;
> 	static double sum;
> 	struct { int rtl_count; unsigned int d;}D;
> 	double f;
> 
> 	if (firstpass) {
> 		if( (fd = open("/dev/rtf0",O_RDONLY) ) < 0 ){
> 			perror("Can't open fifo");
> 			exit(-1);
> 		}
> 		firstpass=0;
> 		n=0;
> 		sum=0.0;
> 		read(fd,&D,sizeof(D));
> 		rtl_count = D.rtl_count;
> 	}
> 	while (0 ==(nbytes= read(fd,&D,sizeof(D))));
> 	if (sizeof(D) != nbytes) {
> 		fprintf(stderr,"read %d ",nbytes);
> 		perror("FIFO failed to block");
> 	}
> #ifdef DEBUG
> 	f = (double)D.d;
> 	f = ((f) * NANOSECONDS_PER_TICK)/1000.0;
> 	n++;
> 	sum+=f;
> 	printf("Delay was %f microseconds, avg=%f, sec=%5d f=%2d, D={ %8d, %08x}\n",
> 		f,sum/(double)n, n/60, 1+(n%60), D.rtl_count, D.d);
> #endif
> 	if(rtl_count && (rtl_count+1 != D.rtl_count))
> 		printf("Dropped %x tics at %x\n",
> 			D.rtl_count-(rtl_count-1), rtl_count);
> 	rtl_count = D.rtl_count;
> //	*tics=rtl_count;
> //	*delta_t=f;
> //	return;
> 	return rtl_count;
> }