From: phil@naic.edu (Phil Perillat Rm 407 X286)
Newsgroups: comp.os.vxworks
Subject: Timer routines for mv147/mv167 boards.....
Date: 8 Oct 92 14:04:23 GMT
Article-I.D.: naic.9210081724.AA15979
Organization: Lawrence Berkeley Laboratory, Berkeley CA
NNTP-Posting-Host: 128.3.112.16
Originator: daemon@vxw.ee.lbl.gov


----- Begin Included Message -----
 
   I am in need of accurate timing on a MVME167.  The TOD clock, a MK48TO8,
has a quanta of only 1 sec.  The MVME manual notes a "tick timer 1 and 2 
counter" on the VMEchip2, and a "TIC timer 1 and 2 counter" on the PCCchip2, 
so I was wondering if anyone might have packaged routines for managing these?

   If not, I'll proceed on, and post them to the archive later.
----- End Included Message -----


I've written some routines that use the auxTimer on the mv147/mv167 boards to
time intervals. You load the routines and start the timer running.
Calling the routine timerValue() then returns the "time" in seconds (as a 
double). The timer
is accurate to 6.25 useconds on the mv147 and 1 usec on the mv167 . There are
probably 10's of useconds in overhead in calling the routine.
"time" is just the time in  seconds since the timer was started.
I usually load the routines at boot time and start the timer going. 
Inside the programs i just call timerValue() multiple times to measure the
intervals of interest.

The auxilliary timer is also used by the spyLib routines in vxWorks so you
can't mix them.

I have another set of routines (not included since they don't have a lot of
comments in them for documentation!!) that uses one of the timers on the
vmechip2 and one of the digital input interrupts on the vmechip2:

1. The usecond timer in the vmechip2 is loaded to count at some submultiple
of 1 second (say 50millisecs). At the interrupt, the timer interrupt count is
incremented, and a timer semaphore is flushed.
 
2. I plug a one second tick from our station clock into the digital input in
the 167 board. This generates an interrupt every second.
The interrupt routine increments the seconds counter, flushes a seconds 
semaphore, and resyncs the usecond timer counter to the 1 second tick.

It provides the following benefits:
- programs can wait on the 1 second, or timer semaphores
- time is available to say the 10's of useconds
- there is no long term drift (of course you'll need a cesium clock like us
   to guarantee this).

Anyway ...

	Here's the code for the mv147/mv167 auxtimer...the other code could
be made available if i ever get around to documenting it...

*******************************************************************************

#include	<vxWorks.h> 
#include	<sysLib.h>
#include        <varargs.h>
#include        <fioLib.h>
#ifdef M68030
#include	<mv147/config.h> 
#define 	TIC_2_CNT  ((unsigned short *)(PCC_BASE_ADRS + 0x16))
#define		TIMER_RES_SEC 6.25e-6
#else
#include	<mv167/config.h>
#define		TIC_2_CNT (PCC2_TIMER2_CNT)
#define		TIMER_RES_SEC 1.e-6
#endif
#define         TICKS_PER_SEC 4

/*******************************************************************************
 * void timerStart()
 *	setup and start the auxiliary timer. 
 *	The aux timer is set to count down every 1/(TICKS_PER_SEC) seconds. It generates
 *	an interrupt, reloads it's counter, and continues counting.
 *	The interrupt routine just counts the number of interrupts.
 *
 *	the routine timerValue() will return the current time in seconds where the current
 *	time is defined as
 *	
 *	   (1./(TICKS_PER_SEC) * number of interrupts) + auxtimervalue*1e-6.
 *	 
 *	the time is returned as a double.
 *
 *	The resolution of the timer is 6.25usecs for the mv147 and 1usec for the mv167.
 
 *	This routine will conflict with the spylib which also uses the auxliary timer.
 *
 *	the routines are:
 *	int    timerStart()
 *	double timerValue()
 *	void   timerIntAO() interrupt routine 
 *
 * EXAMPLE: an example of using the routine would be:
 * 
 * 1. building the routines...
 *
 *	to compile the routines on an mv147 board: 
 *
 *      $(CC) $(CFLAGS) timerAux.c -DM68030 -o timerAux030.o
 *
 *	to compile the routines on an mv167 board: 
 *
 *      $(CC) $(CFLAGS) timerAux.c -DM68040 -o timerAux040.o
 *
 * 2. loading the routines and starting the timer:
 *     at or after boot time enter once:
 *
 *	   ld < timerAux040.o   (or timerAux030.o if you are using a 147)
 *	   timerStart
 *
 *    the timer is now running generating an auxClockInterrput  TICKS_PER_SEC (4) times
 *    per second.
 *
 * 3. to time an interval inside a program... 
 *
 *	   double time1,time2,timedifsecs;
 *	   extern double timerValue();
 *	  
 *	   time1=timerValue();
 *	    ...
 *          ...
 *	   time2=timerValue();
 *	   timedifsecs= time2 - time1;			/* time in secs. accurate to useconds*/
 *
 * END EXAMPLE 
 *   
 *	global variables:
 *	timerIntCount	how many interrupts have arrived.
 *history:
 *09aug92 - changed timerIntCount to a LOCAL variable	
 *15aug92- ticks/sec secs/tick now static globals..
 *07sep92 - added dummy argument to interrupt routine so veclist can print
 *	    out the name
 *
*/
LOCAL  unsigned  int	timerIntCount;	/* how many interrupts we've gotten*/
LOCAL  double		 secs_per_tick;
LOCAL	void timerIntAuxAO(void);
STATUS	timerStart(void)
{
/*     
 *	start the timer going. reset the overflow to 0.
*/
	timerIntCount=0;			/* none so far*/
	secs_per_tick=1./TICKS_PER_SEC; 
	if (sysAuxClkConnect((FUNCPTR)timerIntAuxAO,NULL)
             == ERROR){
	    printf("Error calling sysAuxClkConnect\n");
 	    return(ERROR);
	}
	if (sysAuxClkRateSet(TICKS_PER_SEC) == ERROR){
/*
 *	 they always return error so ignore it...
	    printf("Error calling sysAuxClkrateSet\n");
	    return(ERROR);		
*/
	}
	sysAuxClkEnable();			/* start it going*/
	return(OK);
}
/*******************************************************************************
 * double timerValue()
 *
 *	return current timervalue. must call timerStart once before calling
 *      this routine.
 *	return value is in seconds since call to timerStart.
 *	note i've hardcoded in the 4 ticks per second as .25 . 
*/
double	timerValue()
{
 	return(
         (*TIC_2_CNT)*(double)TIMER_RES_SEC + timerIntCount*
                      secs_per_tick);
}
/*******************************************************************************
 *	    
 *	timerIntAuxAO()
 *
 *	interrupt routine for timerValue
 *	argument is a dummy so veclist will list this routine as a c routine
*/
LOCAL void	timerIntAuxAO(void)
{
	timerIntCount++;
}


phil perillat
arecibo observatory
phil@naic.edu