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

rtl_setclockmode reboots linux




Hi,

I'm using RT-Linux version 2.2.14-rtl2.2 downloaded as prepatched
archive.
After installing I wrote my first rtl module which creates a variable
count of threads which were reading  periodic a byte from a serial port
and write them to fifos.
This was running last week. 
Today, after insmoding the module, I get a reboot of the system.
I needed some tries until I found that the call of 'rtl_setclockmode()'
is the reason.
I attached the file if you want to test this.

What I wanted to test is, if it's possible to have 4-6 threads running
reading with a frequency of 2 kHz
data from a port address (later this should be a A/D board with
analog/digital I/O using comedi as driver),
writing this data to fifos and do some mathematics inside an other RT
process with this data on a Pentium 133 MHz.

I'm new in RTLinux, and I noticed, that the documentation coming with
RTL is very spare. Is there more on writing 
driver and processes? 

I tried to compile 'monotonic' downloaded from the RTL application page,
but I my system miss the file
/usr/src/rtlinux/include/linux/modversions.h. I searched my disc, but
could not find it. I tried to mail to author, but he address is
unreachable. Does someone run 'monotonic' on rtl2.2? 
Maybe it's only working with older versions. If so, which on should I
prefer?


TIA

Vasili

/************************************************************************************************/
all: rtltest.o

rtltest.o: rtltest.c
	make -f /usr/src/rtlinux/rtl.mk $@
/*************************************************************************************************/

/* rtltest.c  */

#include <asm/io.h>
#include <linux/vmalloc.h>
#include <rtl.h>
#include <rtl_fifo.h>
#include <time.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>


int THREADCOUNT=1;
float FREQUENCY=2000; /* frequ. of thread run time in HZ */
int fifo_size=4000;  /*size of rtl fifos*/
unsigned long address = 0x2F8;  /* address of /dev/ttyS0 */

MODULE_PARM ( THREADCOUNT, "i" );
MODULE_PARM_DESC( THREADCOUNT, "Count of threads how will run
concurent");

MODULE_PARM ( FREQUENCY, "i" );
MODULE_PARM_DESC( FREQUENCY, "Frequency of thread calls" );

MODULE_PARM ( WORKTIME, "i" );
MODULE_PARM_DESC( WORKTIME, "Time let thread sleep" );

MODULE_PARM ( address, "i" );

pthread_t *thread;

int init_module ( void );
void cleanup_module ( void );
void delete_threads ( unsigned int first, unsigned int last );
void * start_routine ( void *arg );
void * thread_code ( void *param );


int init_module ( void ) {
	int thread_creation = 0,
		 thread_index = 0;
/*	unsigned long tmp = 0; */
	
	if ( THREADCOUNT > 15 ){
		rtl_printf ( "max of 15 threads! Try again." );
		return -1;
	}
		
	
	thread = (pthread_t *) vmalloc ( sizeof ( pthread_t ) * THREADCOUNT );
	if ( thread == NULL ){
		rtl_printf ( "error allocating memory to store threads\n" );	
		return -1;
	}

	for ( thread_index = 0; thread_index < THREADCOUNT; thread_index++ ) {
		thread_creation = pthread_create ( &thread[thread_index], NULL,
start_routine, (void*)thread_index );
		if ( thread_creation != 0 ) {
			if ( thread_index > 0 ) {
				delete_threads ( 0, thread_index-1 );
			}
			return -1;
		}		
	}
	
	return 0;
}

void cleanup_module ( void ) {
	delete_threads ( 0, THREADCOUNT );
	vfree ( thread );
}

void delete_threads ( unsigned int first, unsigned int last ){
	int Index = 0;
	for( Index = first; Index < last; Index++ ){
		close ( Index );
		rtl_printf ( "fifo %d closed\n", Index );
		rtf_destroy ( Index );	
		rtl_printf ( "fifo %d destroyed\n", Index );
		 
		if ( pthread_delete_np ( thread[Index] ) != 0 )
			rtl_printf ( "can't delete thread number %d\n", Index ) ;
		else
			rtl_printf ( "thread number %d deleted\n", Index );
		
/*
 * 		pthread_cancel ( thread[ Index ] );
 * 		pthread_join ( thread[ Index ] );
 */
		
	}
}

void * start_routine( void *arg ){
	pthread_attr_t attr;
	struct sched_param sched_param;
	int thread_status;
	int thread_index = (int)arg; 
	int fifo_status = 0;
	
	rtl_printf ( "About to create threads number %d\n", thread_index );
	rtl_printf ("RTL rtltest module on CPU %d\n", rtl_getcpuid() );
	pthread_attr_init ( &attr );
	sched_param.sched_priority = 1;
	pthread_attr_setschedparam ( &attr, &sched_param );
	
	
/*
 * 	pthread_setcancelstate ( PTHREAD_CANCEL_ENABLE, NULL );
 * 	pthread_setcanceltype ( PTHREAD_CANCEL_ASYNCHRONOUS );
 */
	

	rtf_destroy ( thread_index );	
	rtl_printf ( "going to create fifo number %d\n", thread_index );
	fifo_status = rtf_create ( thread_index, fifo_size );
	if ( fifo_status ) {
		rtl_printf ( "rtltest fail. fifo_status of fifo number %d = %d\n", 
					    thread_index,
						 fifo_status );
		return (void*)-1;
	}
			
			
	thread_status = pthread_create ( &thread[ thread_index ],  &attr,
thread_code, (void *)thread_index);
	if( thread_status != 0 ){
		rtl_printf( "creation of thread failed.\n" );
		return (void*)-1;	
	}
	
	return (void*)0;
}


void * thread_code ( void *param ) {
	hrtime_t start_time; 
   DECLARE_CPUID(cpu_id); 
	struct timespec resolution;
	unsigned int thread_index = (unsigned int)param;
   unsigned char byte = 0;
	unsigned long ulong = 0, tmplong = 0;
   char fifo_path[ sizeof("/dev/rtf") + 3 ];
	int fd_fifo = -1, written = -1;

	hrtime_t period =  ( 1 / FREQUENCY ) * 1000 * 1000 * 1000; /*period in
nano sec.*/


/*
 * 	int ret = rtl_setclockmode ( rtl_getschedclock(),
RTL_CLOCK_MODE_PERIODIC,
 * 										  period );
 * 	if (ret != 0) {
 * 		rtl_printf("Setting mode failed\n");
 * 		return (void*)-1;
 * 	}
 */

	sprintf ( fifo_path, "/dev/rtf%d", thread_index );
	rtl_printf ( "going to open %s\n", fifo_path );

	fd_fifo = open( fifo_path, O_NONBLOCK );
	if ( fd_fifo < 0 ) {
		rtl_printf ( "/dev/rtf%d open returned %d. errno = %d\n",
				       thread_index, fd_fifo, errno );
		return (void *) -1;
	}
	
	
	/* need to round up the period; should this be done
	 * in pthread_make_periodic? */
	clock_getres (rtl_getschedclock(), &resolution);
	period = timespec_to_ns (&resolution);
	
	rtl_printf ( "thread %d opened fifo", thread_index );
	
/*
 * 	start_time = clock_gethrtime(rtl_getschedclock()) + 2 * period; 
//start at actual time + 2 periods
 * 	pthread_make_periodic_np (pthread_self(), start_time, period);
 */
	
/*
 *  	while ( 1 ){
 * 		
 * 		//do something
 * 		tmplong += 1;
 * 		if ( (tmplong % 100) == 0 )
 * 			rtl_printf ( "thread %d runns %ul times\n", thread_index, tmplong
);
 * 		
 * 		byte = readb ( address );
 * 		ulong = 0xFFF0 | byte;
 * 		written = write ( fd_fifo, &ulong, sizeof( ulong ) );		
 * 		if ( written < sizeof( ulong ) )
 * 			rtl_printf ( "write returned %d. errno = %d", written, errno );
 * 		
 * 		
 * 			
 * 		pthread_wait_np (); // now sleep until next period expires 
 * 	}		
 *  	
 */
	return (void*)0;		  	
}