G.6   Examples

This section provides skeleton code for several types of timestamp drivers. These examples illustrate the issues discussed in G.4 Writing the Driver. However, they are only templates. In their current form they will not compile.

Example G-1:  Timestamp Drivers That Can Be Read While Enabled

This example shows a skeleton timestamp device driver for a hardware timer that can be read while enabled. This type of timer is the simplest to configure for timestamp mode. See Timers That Can Be Read While Enabled, for a discussion of the most important details involved in writing this kind of driver.

/* sampleATimer.c - sample A timer library */ 
 
/* Copyright 1994 Wind River Systems, Inc. */ 
#include "copyright_wrs.h" 
 
/* 
modification history 
-------------------- 
01a,23mar94,dzb  written. 
*/ 
 
/* 
DESCRIPTION 
This library contains sample routines to manipulate the timer functions on 
the sample A chip with a board-independent interface.  This library handles 
the timestamp timer facility. 
 
To include the timestamp timer facility, the macro INCLUDE_TIMESTAMP must be 
defined. 
 
NOTE:  This module provides an example of a VxWorks timestamp timer driver 
for a timer that can be read while enabled.  It illustrates the structures 
and routines discussed in the Appendix, "Creating a VxWorks Timestamp 
Driver."  This module is only a template.  In its current form, it will not 
compile. 
*/ 
 
#ifdef  INCLUDE_TIMESTAMP 
 
#include "drv/timer/timestampDev.h" 
#include "drv/timer/sampleATimer.h" 
 
/* Locals */  
 
LOCAL BOOL    sysTimestampRunning = FALSE;      /* running flag */ 
LOCAL FUNCPTR sysTimestampRoutine = NULL;       /* user rollover routine */ 
LOCAL int     sysTimestampArg     = NULL;       /* arg to user routine */ 
 
/*************************************************************************** 
* 
* sysTimestampInt - timestamp timer interrupt handler 
* 
* This routine handles the timestamp timer interrupt.  A user routine is 
* called, if one was connected by sysTimestampConnect(). 
* 
* RETURNS: N/A    
* 
* SEE ALSO: sysTimestampConnect() 
*/ 
 
LOCAL void sysTimestampInt (void) 
    { 
    /* acknowledge the timer rollover interrupt here */ 
 
    if (sysTimestampRoutine != NULL)    /* call user-connected routine */ 
        (*sysTimestampRoutine) (sysTimestampArg); 
    } 
 
/*************************************************************************** 
* 
* sysTimestampConnect - connect a user routine to the timestamp timer 
*                         interrupt 
* 
* This routine specifies the user interrupt routine to be called at each 
* timestamp timer interrupt.  It does not enable the timestamp timer itself. 
* 
* RETURNS: OK, or ERROR if sysTimestampInt() interrupt handler is not used. 
*/ 
  
STATUS sysTimestampConnect 
    ( 
    FUNCPTR routine,    /* called at each timestamp timer interrupt */ 
    int arg             /* argument with which to call routine */ 
    ) 
    { 
    sysTimestampRoutine = routine; 
    sysTimestampArg = arg; 
    return (OK); 
    } 
 
/*************************************************************************** 
* 
* sysTimestampEnable - initialize and enable the timestamp timer 
* 
* This routine connects the timestamp timer interrupt and initializes the 
* counter registers.  If the timestamp timer is already running, this routine 
* merely resets the timer counter. 
* 
* Set the rate of the timestamp timer input clock explicitly within the 
* BSP, in the sysHwInit() routine.  This routine does not initialize 
* the timer clock rate. 
* 
* RETURNS: OK, or ERROR if the timestamp timer cannot be enabled. 
*/ 
  
STATUS sysTimestampEnable (void) 
    { 
    if (sysTimestampRunning) 
        { 
        /* clear the timer counter here */ 
 
        return (OK); 
        } 
     
    /* connect interrupt handler for the timestamp timer */ 
 
    (void) intConnect (INUM_TO_IVEC (XXX), sysTimestampInt, NULL); 
 
    sysTimestampRunning = TRUE; 
 
    /* set the timestamp timer's interrupt vector to XXX (if necessary) */ 
    /* reset & enable the timestamp timer interrupt */ 
 
    /* set the period of timestamp timer (see sysTimestampPeriod()) */ 
  
    /* clear the timer counter here */ 
    /* enable the timestamp timer here */ 
  
    return (OK); 
    } 
 
/*************************************************************************** 
* 
* sysTimestampDisable - disable the timestamp timer 
* 
* This routine disables the timestamp timer.  Interrupts are not disabled. 
* However, the tick counter will not increment after the timestamp timer 
* is disabled, ensuring that interrupts are no longer generated. 
* 
* RETURNS: OK, or ERROR if the timestamp timer cannot be disabled. 
*/ 
  
STATUS sysTimestampDisable (void) 
    { 
    if (sysTimestampRunning) 
        { 
        /* disable the timestamp timer here */ 
 
        sysTimestampRunning = FALSE; 
        } 
 
    return (OK); 
    } 
 
/*************************************************************************** 
* 
* sysTimestampPeriod - get the timestamp timer period 
* 
* This routine returns the period of the timer in timestamp ticks. 
* The period, or terminal count, is the number of ticks to which the 
* timestamp timer counts before rolling over and restarting the counting 
* process. 
* 
* RETURNS: The period of the timer in timestamp ticks. 
*/ 
  
UINT32 sysTimestampPeriod (void) 
    { 
    /* 
     * Return the timestamp timer period here. 
     * The highest period (maximum terminal count) should be used so 
     * that rollover interrupts are kept to a minimum. 
     */ 
    } 
 
/*************************************************************************** 
* 
* sysTimestampFreq - get the timestamp timer clock frequency 
* 
* This routine returns the frequency of the timer clock, in ticks per second. 
* The rate of the timestamp timer should be set explicitly in the BSP, 
* in the sysHwInit() routine. 
* 
* RETURNS: The timestamp timer clock frequency, in ticks per second. 
*/ 
  
UINT32 sysTimestampFreq (void) 
    { 
    UINT32 timerFreq; 
 
    /* 
     * Return the timestamp tick output frequency here. 
     * This value can be determined from the following equation: 
     *     timerFreq = clock input frequency / prescaler 
     *  
     * When possible, read the clock input frequency and prescaler values 
     * directly from chip registers. 
     */ 
  
    return (timerFreq); 
    } 
 
/*************************************************************************** 
* 
* sysTimestamp - get the timestamp timer tick count 
* 
* This routine returns the current value of the timestamp timer tick counter. 
* The tick count can be converted to seconds by dividing by the return of 
* sysTimestampFreq(). 
* 
* Call this routine with interrupts locked.  If interrupts are 
* not already locked, use sysTimestampLock() instead. 
* 
* RETURNS: The current timestamp timer tick count. 
* SEE ALSO: sysTimestampLock() 
*/ 
  
UINT32 sysTimestamp (void) 
    { 
    /* return the timestamp timer tick count here */ 
    } 
 
/*************************************************************************** 
* 
* sysTimestampLock - get the timestamp timer tick count 
* 
* This routine returns the current value of the timestamp timer tick counter. 
* The tick count can be converted to seconds by dividing by the return of 
* sysTimestampFreq(). 
* 
* This routine locks interrupts for cases where it is necessary to stop the 
* tick counter before reading it, or when two independent counters must 
* be read.  If interrupts are already locked, use sysTimestamp() instead. 
* 
* RETURNS: The current timestamp timer tick count. 
* 
* SEE ALSO: sysTimestamp() 
*/ 
  
UINT32 sysTimestampLock (void) 
    { 
    /* 
     * Return the timestamp timer tick count here. 
     * Interrupts do *not* need to be locked in this routine if 
     * the counter need not be stopped before reading. 
     */ 
    } 
 
#endif  /* INCLUDE_TIMESTAMP */

Example G-2:  Timestamp Drivers for Deficient Timers

This example shows a skeleton timestamp device driver for a hardware timer that cannot be read while enabled, requires preloading, and counts down. See Working Around Deficiencies in Hardware Timers, for a discussion of the most important details involved in writing this kind of driver.

/* sampleBTimer.c - sample B timer library */ 
 
/* Copyright 1984-1994 Wind River Systems, Inc. */ 
#include "copyright_wrs.h" 
 
/*
modification history -------------------- 01a,23mar94,dzb written. */ /* DESCRIPTION This library contains sample routines to manipulate the timer functions on the sample B chip with a board-independent interface. This library handles the timestamp timer facility. To include the timestamp timer facility, the macro INCLUDE_TIMESTAMP must be defined. To support the timestamp timer facility, two timers are used: a counting timer, and a correction timer. The counting timer is used as the timestamp counter, but must be stopped to be read, thereby introducing time skew. The correction timer periodically resets the counting timer in an effort to alleviate cumulative time skew. In addition, the correction timer interrupt is used for one other purpose: to alert the user to a counting timer reset (analogous to a timestamp rollover event). The TS_CORRECTION_PERIOD macro defines the period of the correction timer, which translates to the period of the counting timer reset (analogous to a timestamp rollover event). The TS_SKEW macro can be used to compensate for time skew incurred when the counting timer is stopped in sysTimestamp() and sysTimestampLock(). The value of TS_SKEW is subtracted from the stopped timestamp counter in an attempt to make up for "lost" time. The correct value to adjust the timestamp counter is not only board-dependent, it is influenced by CPU speed, cache mode, memory speed, and so on. NOTE: This module provides an example of a VxWorks timestamp timer driver for a timer that cannot be read while enabled, requires preloading, and counts down. It illustrates the structures and routines discussed in the Appendix, "Creating a VxWorks Timestamp Driver." This module is only a template. In its current form, it will not compile. */ /* includes */ #include "drv/timer/timestampDev.h" #include "drv/timer/sampleBTimer.h" #ifdef INCLUDE_TIMESTAMP /* defines */ #ifndef TS_CORRECTION_PERIOD #define TS_CORRECTION_PERIOD 0xXXX... /* timestamp skew correction per. */ #endif /* TS_CORRECTION_PERIOD */ /* see sysTimestampPeriod() */ #ifndef TS_SKEW #define TS_SKEW 0 /* timestamp skew correction time */ #endif /* TS_SKEW */ /* locals */ LOCAL BOOL sysTimestampRunning = FALSE; /* running flag */ LOCAL FUNCPTR sysTimestampRoutine = NULL; /* user rollover routine */ LOCAL int sysTimestampArg = NULL; /* arg to user routine */ /*************************************************************************** * * sysTimestampInt - correction timer interrupt handler * * This routine handles the correction timer interrupt. A user routine is * called, if one was connected by sysTimestampConnect(). * * RETURNS: N/A * * SEE ALSO: sysTimestampConnect() */ LOCAL void sysTimestampInt (void) { /* acknowledge the correction timer interrupt here */ sysTimestampEnable (); if (sysTimestampRoutine != NULL) /* call user-connected routine */ (*sysTimestampRoutine) (sysTimestampArg); } /*************************************************************************** * * sysTimestampConnect - connect a user routine to the timestamp timer *  interrupt * * This routine specifies the user interrupt routine to be called at each * timestamp timer interrupt. It does not enable the timestamp timer itself. * * RETURNS: OK, or ERROR if sysTimestampInt() interrupt handler is not used. */ STATUS sysTimestampConnect ( FUNCPTR routine, /* routine called at each timestamp timer interrupt */ int arg /* argument with which to call routine */ ) { sysTimestampRoutine = routine; sysTimestampArg = arg; return (OK); } /*************************************************************************** * * sysTimestampEnable - initialize and enable the timestamp timer * * This routine connects the timestamp timer interrupt and initializes the * counter registers. If the timestamp timer is already running, this routine * merely resets the timer counter. * * Set the rate of the timestamp timer input clock explicitly within the * BSP, in the sysHwInit() routine. This routine does not initialize * the timer clock rate. * * RETURNS: OK, or ERROR if the timestamp timer cannot be enabled. */ STATUS sysTimestampEnable (void) { int lockKey; if (sysTimestampRunning) { lockKey = intLock (); /* LOCK INTERRUPTS */
/* disable the counting timer here */ /* preload the reset count here */ /* enable the counting timer here */ /* wait for preload to take effect here */ intUnlock (lockKey); /* UNLOCK INTERRUPTS */ return (OK); } /* connect interrupt handler for the correction timer */ (void) intConnect (INUM_TO_IVEC (XXX), sysTimestampInt, NULL); /* set the correction timer's interrupt vector to XXX (if necessary) */ sysTimestampRunning = TRUE; /* set the period of the correction timer (see sysTimestampPeriod()) */ /* set the period of the counting timer = reset count */ /* enable the counting timer here */ /* enable the correction timer here */ /* wait for preload to take effect on both timers here */ return (OK); } /*************************************************************************** * * sysTimestampDisable - disable the timestamp timer * * This routine disables the timestamp timer. Interrupts are not disabled. * However, the tick counter will not decrement after the timestamp timer * is disabled, ensuring that interrupts are no longer generated. * * RETURNS: OK, or ERROR if the timestamp timer cannot be disabled. */ STATUS sysTimestampDisable (void) { if (sysTimestampRunning) { sysTimestampRunning = FALSE; /* disable the correction timer here */ /* disable the counting timer here */ } return (OK); } /*************************************************************************** * sysTimestampPeriod - get the timestamp timer period * * This routine returns the period of the timer in timestamp ticks. * The period, or terminal count, is the number of ticks to which the * timestamp timer counts before rolling over and restarting the counting * process. * * RETURNS: The period of the timer in timestamp ticks. */ UINT32 sysTimestampPeriod (void) { /* * Return the correction timer period here. * A reasonable correction period should be chosen. A short period * causes increased CPU overhead due to correction timer interrupts. * A long period allows for a large accumulation of time skew * due to sysTimestamp() calls stopping the counting timer. */ return (TS_CORRECTION_PERIOD); } /*************************************************************************** * sysTimestampFreq - get the timestamp timer clock frequency * * This routine returns the frequency of the timer clock, in ticks per second. * The rate of the timestamp timer should be set explicitly in the BSP, * in the sysHwInit() routine. * * RETURNS: The timestamp timer clock frequency, in ticks per second. */ UINT32 sysTimestampFreq (void) { UINT32 timerFreq; /* * Return the timestamp tick output frequency here. * This value can be determined from the following equation: * timerFreq = clock input frequency / prescaler * * When possible, read the clock input frequency and prescaler values * directly from chip registers. */ return (timerFreq); } /*************************************************************************** * * sysTimestamp - get the timestamp timer tick count * * This routine returns the current value of the timestamp timer tick counter. * The tick count can be converted to seconds by dividing by the return of * sysTimestampFreq(). * * Call this routine with interrupts locked. If interrupts are * not already locked, use sysTimestampLock() instead. * * RETURNS: The current timestamp timer tick count. * * SEE ALSO: sysTimestampLock() */ UINT32 sysTimestamp (void) { UINT32 tick = 0; register UINT32 * pTick; register UINT32 * pPreload; if (sysTimestampRunning) { /* pTick = counter read register location */ /* pPreload = counter preload register location */ /* disable counting timer here */ tick = *pTick; /* read counter value */ *pPreload = tick - TS_SKEW; /* set preload value (with time-skew adjustment) */ /* enable counting timer here */ tick -= (0xfff...); /* adjust to incrementing value */ } return (tick); } /*************************************************************************** * sysTimestampLock - get the timestamp timer tick count * * This routine returns the current value of the timestamp timer tick counter. * The tick count can be converted to seconds by dividing by the return of * sysTimestampFreq(). * * This routine locks interrupts for cases where it is necessary to stop the * tick counter before reading it, or when two independent counters must * be read. If interrupts are already locked, use sysTimestamp() instead. * * RETURNS: The current timestamp timer tick count. * SEE ALSO: sysTimestamp() */ UINT32 sysTimestampLock (void) { UINT32 tick = 0; register UINT32 * pTick; register UINT32 * pPreload; int lockKey; if (sysTimestampRunning) { lockKey = intLock (); /* LOCK INTERRUPTS */ /* pTick = counter read register location */ /* pPreload = counter preload register location */ /* disable counting timer here */ tick = *pTick; /* read counter value */ *pPreload = tick - TS_SKEW; /* set preload value */  /* (with time-skew adjustment) */ /* enable counting timer here */ intUnlock (lockKey); /* UNLOCK INTERRUPTS */ tick -= (0xfff...); /* adjust to incrementing value */ } return (tick); } #endif /* INCLUDE_TIMESTAMP */

Example G-3:  Timestamp Drivers for the VxWorks System Clock Timer

This example shows a skeleton timestamp driver for systems that have no suitable spare timers, so that timestamps must be derived from the VxWorks system clock timer. See Using the VxWorks System Clock Timer, for a discussion of the most important details involved in writing this kind of driver.

/* sampleCTimer.c - sample C timer library */ 
 
/* Copyright 1994 Wind River Systems, Inc. */ 
#include "copyright_wrs.h" 
 
/* 
modification history 
-------------------- 
01a,23mar94,dzb  written. 
*/ 
 
/* 
DESCRIPTION 
This library contains sample routines to manipulate the timer functions on 
the sample C chip with a board-independent interface.  This library handles 
the timestamp timer facility. 
 
To include the timestamp timer facility, the macro INCLUDE_TIMESTAMP must be 
defined.
NOTE: This module provides an example of a VxWorks timestamp timer driver implemented by reading the system clock timer counter. It illustrates the structures and routines discussed in the Appendix, "Creating a VxWorks Timestamp Driver." This module is only a template. In its current form, it will not compile. */ #ifdef INCLUDE_TIMESTAMP #include "drv/timer/timestampDev.h" #include "drv/timer/sampleCTimer.h" /* Locals */ LOCAL BOOL sysTimestampRunning = FALSE; /* running flag */ /*************************************************************************** * * sysTimestampConnect - connect a user routine to the timestamp timer *  interrupt * * This routine specifies the user interrupt routine to be called at each * timestamp timer interrupt. It does not enable the timestamp timer itself. * * RETURNS: OK, or ERROR if sysTimestampInt() interrupt handler is not used. */ STATUS sysTimestampConnect ( FUNCPTR routine, /* routine called at each timestamp timer interrupt */ int arg /* argument with which to call routine */ ) { /* ERROR indicates that the system clock tick specifies a rollover event */ return (ERROR); } /*************************************************************************** * * sysTimestampEnable - initialize and enable the timestamp timer * * This routine connects the timestamp timer interrupt and initializes the * counter registers. If the timestamp timer is already running, this routine * merely resets the timer counter. * * Set the rate of the timestamp timer input clock explicitly within the * BSP, in the sysHwInit() routine. This routine does not initialize * the timer clock rate. * * RETURNS: OK, or ERROR if the timestamp timer cannot be enabled. */
STATUS sysTimestampEnable (void) { if (sysTimestampRunning) return (OK); sysTimestampRunning = TRUE; sysClkEnable (); /* ensure the system clock is running */ return (OK); } /*************************************************************************** * sysTimestampDisable - disable the timestamp timer * * This routine disables the timestamp timer. Interrupts are not disabled. * However, the tick counter does not increment after the timestamp timer * is disabled, ensuring that interrupts are no longer generated. * * RETURNS: OK, or ERROR if the timestamp timer cannot be disabled. */ STATUS sysTimestampDisable (void) { sysTimestampRunning = FALSE; return (ERROR); } /*************************************************************************** * * sysTimestampPeriod - get the timestamp timer period * * This routine returns the period of the timer in timestamp ticks. * The period, or terminal count, is the number of ticks to which the * timestamp timer counts before rolling over and restarting the counting * process. * * RETURNS: The period of the timer in timestamp ticks. */ UINT32 sysTimestampPeriod (void) { /* return the system clock period in timestamp ticks */ return (sysTimestampFreq ()/sysClkRateGet ()) } /*************************************************************************** * * sysTimestampFreq - get the timestamp timer clock frequency * * This routine returns the frequency of the timer clock, in ticks per second. * The rate of the timestamp timer should be set explicitly in the BSP, * in the sysHwInit() routine. * * RETURNS: The timestamp timer clock frequency, in ticks per second. */ UINT32 sysTimestampFreq (void) { UINT32 timerFreq; /* * Return the timestamp tick output frequency here. * This value can be determined from the following equation: * timerFreq = clock input frequency / prescaler * * When possible, read the clock input frequency and prescaler values * directly from chip registers. */ return (timerFreq); } /*************************************************************************** * * sysTimestamp - get the timestamp timer tick count * * This routine returns the current value of the timestamp timer tick counter. * The tick count can be converted to seconds by dividing by the return of * sysTimestampFreq(). * * Call this routine with interrupts locked. If interrupts are * not already locked, use sysTimestampLock() instead. * * RETURNS: The current timestamp timer tick count. * SEE ALSO: sysTimestampLock() */ UINT32 sysTimestamp (void) { /* return the system clock timer tick count here */ } /*************************************************************************** * * sysTimestampLock - get the timestamp timer tick count * * This routine returns the current value of the timestamp timer tick counter. * The tick count can be converted to seconds by dividing by the return of * sysTimestampFreq(). * * This routine locks interrupts for cases where it is necessary to stop the * tick counter before reading it, or when two independent counters must * be read. If interrupts are already locked, use sysTimestamp() instead. * * RETURNS: The current timestamp timer tick count. * * SEE ALSO: sysTimestamp() */ UINT32 sysTimestampLock (void) { /* * Return the system clock timer tick count here. * Interrupts do *not* need to be locked in this routine if * the counter does not need to be stopped to be read. */ } #endif /* INCLUDE_TIMESTAMP */