MVME167 usec timer?

MVME167 usec timer?

Post by Carl La » Fri, 09 Oct 1992 05:46:25



   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.

                                        Carl Lacy,  MS 3F
                                        Charles Stark Draper Laboratory
                                        555 Technology Square
                                        Cambridge, Mass.   02139
                                           (617) 258-3228
                                           (617) 258-1880 (fax)

 
 
 

MVME167 usec timer?

Post by Bob Herlie » Fri, 09 Oct 1992 00:59:25


My usrTime functions (in ntpvx* on the archive, part of my NTP port)
includes gettimeofday() function that returns time in a struct timeval.
Struct timeval has a precision of microseconds.  To actually get this
precision, you need to implement microtime() for your hardware.  If you
don't write a microtime(), you'll get time to the nearest tick (usually
167 milliseconds).

UsrTime has drivers for the SBE VPU-30.  For time of day clock, that includes
a driver for the MK48T02 time of day chip, which, as you noted, has a
precision of seconds.  By chaining onto the system tick, we increase the
resolution to 1 tick.  The microtime() function is needed for microsecond
(actually 4 usec for SBE VPU-30) precision.  The drivers I wrote and included,
for the SBE VPU-30, talk to the MC68230 PIT chip to derive microseconds.
The VxWorks BSP uses the PIT to generate 60 Hz for the system clock, and
my microtime() simply reads the current value in the count register to
determine the microsecond offset from the clock tick.

Here's the microtime() module for the MC63230 for SBE.  You can pick up
usrTime from the archives, in which case you get a bunch of Unix compatible
time functions, or you can simply look at what I've done and use a similar
trick for your hardware.  In either case, you'll need to write some software
that pokes around in the hardware that generates your clock tick.

/* microtime.s - get microseconds from clock tick       */

/*
modification history
--------------------
14 sept 90, rah, created

DESCRIPTION
This module contains a routine to get high resolution data about current
time.  It returns the number of microseconds until the next clock tick.
It is specific to the SBE VPU30, and has a resolution of 4 microseconds.
*/

#define ASMLANGUAGE
#include "vpu30.h"

#define PIT_CNT_REG     (PIT_BASE + 0x2c)

        .text
        .even

        .globl  _microtime

/*******************************************************************************
*
* microtime - get microseconds until next clock tick
* This routine gets number of microseconds until the next clock tick.
* Since the movepl takes 4 bus cycles, and the clock is running during
* this time, the answer can reflect some bytes in which a carry took
* place and other bytes in which it didn't.  However, since the movepl
* takes much less than a microsecond, and the clock counts at 4 microsecond
* intervals, this carry error could only have happened if the LSB is 00.
* So, we check for an LSB of zero and try again in that case.
*
* RETURNS: Number of microseconds until next clock tick (unsigned long)
*/

_microtime:

        moveal  #PIT_CNT_REG, a0        /* get address of PIT_CNT*/
mt_retry:
        movepl  (0,a0), d0              /* get current count    */
        orb     d0, d0                  /* test for LSB == 0    */
        beq     mt_retry                /* if so, answer may be wrong*/

        asll    #2, d0                  /* multiply count by 4 to get usec*/

        rts

--------------------------------------------------------------
Bob Herlien
MBARI (Monterey Bay Aquarium Research Institute)

"Limit congressmen to two terms.  One in office.  One in jail."

 
 
 

MVME167 usec timer?

Post by Eric L. Scho » Tue, 13 Oct 1992 21:04:02


In article <9210072046.AA01...@coyote.draper.com>, l...@draper.com (Carl Lacy) writes:

>    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?

Below is a package which should meet your needs.  This uses
unix standard gettimeofday, settimeofday, and adjtime.  Accurate
to 1 microseconds.  Calls to gettimeofday without a timezone
take about 5.5 microseconds.  This package works with the NTP
packages available for VxWorks (see archives).  
--

Eric L. Schott,    HRB Systems, Inc.    814/238-4311     e...@icf.hrb.com
  "As we acquire more knowledge, things do not become more comprehensible
   but more mysterious."                  Albert Schweitzer, "Paris Notes"

---------------------------------------------------------------------------
/*
 *      (U) The Timer_Library provides gettimeofday and
 *      settimeofday functionality for the MVME167 card.  This library
 *      has been extended to support NTP.  Therefore, this 167 can be
 *      closely synchronized with other CPUs on the network.  See the
 *      VxWorks NTP documentation for further details.
 *
 *      (U) The functions within the Timer_Library software are
 *      called as needed based on their prototypes as found in
 *      Prototypes.h.
 *
 *      (U) The TOD_Init routine MUST be called AFTER the clock
 *      has been set or reset (via sysClkRateSet).
 *
 */

#include <vxWorks.h>
#include <sysLib.h>
#include <intLib.h>
#include <68k/iv.h>
#include <stdioLib.h>
#include <string.h>
#include <limits.h>
#include <wdLib.h>

#define J68KTIM_USEC_PER_SEC 1000000
/*
 *.             (U) Number of microseconds per second
 *.
 *.
 */
struct timeval {
        long    tv_sec;         /* seconds */
        long    tv_usec;        /* and microseconds */

};

struct timezone {
        int     tz_minuteswest; /* minutes west of Greenwich */
        int     tz_dsttime;     /* type of dst correction */
};

#define DST_NONE        0       /* not on dst */
#define DST_USA         1       /* USA style dst */
#define DST_AUST        2       /* Australian style dst */
#define DST_WET         3       /* Western European dst */
#define DST_MET         4       /* Middle European dst */
#define DST_EET         5       /* Eastern European dst */
#define DST_CAN         6       /* Canada */
#define DST_GB          7       /* Great Britain and Eire */
#define DST_RUM         8       /* Rumania */
#define DST_TUR         9       /* Turkey */
#define DST_AUSTALT     10      /* Australian style with shift in 1986 */
#define ITIMER_REAL     0
#define ITIMER_VIRTUAL  1
#define ITIMER_PROF     2
struct  itimerval {
        struct  timeval it_interval;    /* timer interval */
        struct  timeval it_value;       /* current value */

};

/*
 *      Local Commons and Data Items
 */
#define VMECHIP2_BASE_ADRS 0xfff40000
#include <drv/vmechip2.h>
/*
 *.             (U) Define the VMEchip2 registers
 */

#define TIMEOUTCR_PA_MASK 0xff
/*
 *.             (U) Mask for Prescaler Ajdust in Prescaler Control
 *.             Register of VMEchip2.  
 */

#define TIMEOUTCR_PA_25_MHZ 0xe7
/*
 *.             (U) Prescaler Ajdust for our 68040 speed.
 */

#define TIMERCR_TT1_OVF_SHIFT (4)
/*
 *.             (U) Tick Timer Control Register overflow counter.
 */

#define TIMERCR_TT1_OVF (0xf << TIMERCR_TT1_OVF_SHIFT)
/*
 *.             (U) Tick Timer Control Register overflow counter.
 */

#define IOCR_VBR0_SHIFT (28 - 4)
/*
 *.             (U) Mask for VMEchip2 interrupt vector selection.
 */

#define IOCR_VBR1_SHIFT (24 - 4)
/*
 *.             (U) Mask for VMEchip2 interrupt vector selection.
 */

#define IOCR_VBR0_MASK 0xf0000000
/*
 *.             (U) Mask for VMEchip2 interrupt vector selection.
 */

#define IOCR_VBR1_MASK 0x0f000000
/*
 *.             (U) Mask for VMEchip2 interrupt vector selection.
 */

#define ADJTIME_MAX     ((INT_MAX / J68KTIM_USEC_PER_SEC) - 1)
/*
 *.             (U) Maximum time to adjust clock.
 */

unsigned int hz;
/*
 *.             (U) sysclock interrupt rate per seconds.  This is
 *.             global for NTP.
 *.
 *.             Units:           interrupts per seconds
 *.             Accuracy:        N/A
 *.             Precision:       N/A
 *.             Range:           N/A
 *.             Default:         TRUE or FALSE
 */

unsigned int tick;
/*
 *.             (U) Number of microseconds in clock tick.  This is
 *.             global for NTP.
 *.
 *.             Units:           microseconds
 *.             Accuracy:        N/A
 *.             Precision:       N/A
 *.             Range:           N/A
 *.             Default:         N/A
 */

volatile int tickadj = 500;
/*
 *.             (U) Number of microseconds to adjust time of day clock
 *.             every adjustment interval (one second).  This is
 *.             global for NTP.
 *.
 *.             Units:           microseconds
 *.             Accuracy:        N/A
 *.             Precision:       N/A
 *.             Range:           1 - 250,000 (1/4 s)
 *.             Default:         500
 */

LOCAL int adj_time = 0;
/*
 *.             (U) How much time to adjust timeofday clock
 *.
 *.             Units:           microseconds
 *.             Accuracy:        N/A
 *.             Precision:       N/A
 *.             Range:           +/- ADJTIME_MAX
 *.             Default:         Zero
 */

LOCAL int timerInitCalled=FALSE;
/*
 *.             (U) Indicates if timer initialized.
 *.
 *.             Units:           Boolean
 *.             Accuracy:        N/A
 *.             Precision:       N/A
 *.             Range:           N/A
 *.             Default:         TRUE or FALSE
 */

LOCAL long currentSecond=0;
/*
 *.             (U) This is the current second past Epoch.  However,
 *.             the concept of Epoch is muddied here since we have no
 *.             guarantee settimeofday has been called to set the
 *.             seconds based upon Jan 1, 1970.  Most likey, Epoch is
 *.             time since the board last booted.
 *.
 *.             Units:           seconds
 *.             Accuracy:        one second
 *.             Precision:       N/A
 *.             Range:           N/A
 *.             Default:         N/A
 */

LOCAL struct timezone currentZone = {5*60,DST_USA};
/*
 *.             (U) Current time zone.  Must be set by settimeofday
 *.             for the value to be valid.
 *.
 *.             Units:           N/A
 *.             Accuracy:        N/A
 *.             Precision:       N/A
 *.             Range:           N/A
 *.             Default:         Eastern timezone, USA DST
 */

LOCAL WDOG_ID adjust_wd_timer;
/*
 *.             (U) When doing an adjustment of the time of day clock,
 *.             it is simplest if the adjustment is made in the middle
 *.             of a second.  This means if we either add or subtract
 *.             from the microseconds in a second, we do not have to
 *.             worry about the time rolling over into another second.
 *.             We use this timer to create an interrupt at near the
 *.             one-half second interval.
 *.
 *.             Units:           N/A
 *.             Accuracy:        N/A
 *.             Precision:       N/A
 *.             Range:           N/A
 *.             Default:         N/A
 */

LOCAL unsigned int adjust_wd_ticks;
/*
 *.             (U) Number of ticks to wait to call adjustment routine.
 *.
 *.             Units:           VxWorks ticks
 *.             Accuracy:        N/A
 *.             Precision:       N/A
 *.             Range:           N/A
 *.             Default:         N/A
 */

/********************* Adjust_Clock ***********************
 *
 *      (U) Adjust_Clock adjusts the time of day clock.
 *
 *      (U) Adjust_Clock adjusts the time of day clock.  This
 *      routine should be called at the 1/2 second interval if there
 *      is an adjustment to be made.  It adds/subtracts the adjustment
 *      interval from the VMECHIP2 timer.
 *
 *      (U) The calling parameters for this routine are:
 *          
 */
LOCAL void  Adjust_Clock
  (
   int parameter
/*
 *.             (U) Unused VxWorks parameter.
 *.
 *.             Type:            Input
 *.             Units:           N/A
 *.             Accuracy:        N/A
 *.             Precision:       N/A
 *.             Range:           N/A
 *.            
 */
  )
{
   int cur_adj;
/*
 *.             (U) Amount to adjust clock in current second.
 *.
 *.             Units:           Microseconds
 *.             Accuracy:        N/A
 *.             Precision:       N/A
 *.             Range:           0 -> +/-  tickadj
 *.            
 */

  volatile int *ireg;
/*
 *.             (U)  points to hardware register
 *.
 *.             Units:           N/A
 *.             Accuracy:        N/A
 *.             Precision:       N/A
 *.             Range:           N/A
 *.            
 */

   cur_adj = max(min(adj_time,tickadj),-tickadj); /* Calc adjustment */
   if (cur_adj != 0)                     /* if adjustment required */
     {
     ireg = VMECHIP2_TTCOUNT1;
     *ireg += cur_adj;
     adj_time -=  cur_adj;
     }
   return;

}

/********************* TOD_Isr ***********************
 *
 *      (U) TOD_Isr is the Time of Day interrupt service routine.
 *
 *      (U) TOD_Isr resets the VMEchip2 microseconds timer and
 *      maintains the count of seconds past the "Epoch."
 *
 *      (U) The calling parameters for this routine are:
 *          
 */
LOCAL void TOD_Isr
  (
   int param
/*
 *.             (U) Unused intConnect parameter
 *.
 *.             Type:            Input
 *.             Units:           N/A
 *.             Accuracy:        N/A
 *.             Precision:       N/A
 *.             Range:           N/A
 *.            
 */
  )
{
  volatile int *ireg;
/*
 *.             (U)  points to hardware register
 *.
 *.             Units:           N/A
 *.             Accuracy:        N/A
 *.             Precision:       N/A
 *.             Range:           N/A
 *.            
 */

  ireg = VMECHIP2_ICLR;                  /* Interrupt clear register */
  *ireg |=
...

read more »

 
 
 

1. 100 usec timer resolution under NT

Hello,

we need to output some values to an analog output card. The time
between two outputs should be approx. 100 usec. Because NT is
no real time system my idea is to write a device driver to do this
task. It should program the 8254 to setup the interrupt frequency
of 100 usec. Because interrupt #0 has highest priority it should
give a predictable response. Then of course I must hook the
interrupt service routine for interrupt #0 and redirect the interrupt
to the original service routine only if the timer is not caused by
my reprogramming.

Has any one experience with this type of task? Is any driver example
available? Should I reprogram timer #0 of the 8254 or is timer #1
available (in former times this timer has been used for DRAM refresh)?
I think this is the same idea that are behind some real time extensions
for NT. But for my task dealing with a real time extension seems to
to be an overkill for me.

Any advise is greatly appreciated.

Kind regards
Siegmund Baumann

2. 10gig SCSI hard drives, Exabyte tape drive 1.00 dollar each

3. MVME167 PCC2 Timer Routines

4. Of Cell Phones (Kyocera / Treo) and GPS

5. Timers and timer device

6. _HELP_ Uniterm U/l

7. Besides system main timer,what other kind of timer we can use?

8. discuss forum?!?

9. rtc cmos timer/system timer

10. How To define 200us Real-Timer Timer In WDM?

11. gettimeofday() (usec clock)

12. usec Delay on a MPC850

13. Memory Channel: Message Passing Latency 5.8 usecs, ~60 MB/sec @ 4KB messages