Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:48

0001 /*
0002  *  This port does not allow the application to select which timer on the
0003  *  MVME167 to use for the clock, nor does it allow the application to
0004  *  configure the clock. The clock uses the VMEchip2 Tick Timer #2. This
0005  *  timer is set up to raise a MC680x0 level-6 interrupt every 1 ms. The
0006  *  interrupt vector is 0x69.
0007  *
0008  *  All page references are to the MVME166/MVME167/MVME187 Single Board
0009  *  Computer Programmer's Reference Guide (MVME187PG/D2) with the April
0010  *  1993 supplements/addenda (MVME187PG/D2A1).
0011  */
0012 
0013 /*
0014  *  COPYRIGHT (c) 1989-1999.
0015  *  On-Line Applications Research Corporation (OAR).
0016  *
0017  *  The license and distribution terms for this file may be
0018  *  found in the file LICENSE in this distribution or at
0019  *  http://www.rtems.org/license/LICENSE.
0020  *
0021  *  Modifications of respective RTEMS files:
0022  *  Copyright (c) 1998, National Research Council of Canada
0023  */
0024 
0025 #include <stdlib.h>
0026 #include <bsp.h>
0027 #include <rtems/clockdrv.h>
0028 
0029 #define MS_COUNT          1000              /* T2's countdown constant (1 ms) */
0030 #define CLOCK_INT_LEVEL   6                 /* T2's interrupt level */
0031 #define CLOCK_VECTOR (VBR0 * 0x10 + 0x9)    /* T2 is vector $X9 (p. 2-71)*/
0032 
0033 /*
0034  *  Clock_driver_ticks is a monotonically increasing counter of the number of
0035  *  VMEchip2 timer #2 ticks since the driver was initialized.
0036  */
0037 volatile uint32_t Clock_driver_ticks;
0038 
0039 /*
0040  *  Clock_isrs is the number of clock ISRs until the next invocation of the
0041  *  RTEMS clock tick routine. This clock tick device driver gets an interrupt
0042  *  once a millisecond and counts down until the length of time between the
0043  *  user configured microseconds per tick has passed. This allows the clock
0044  *  device to "tick" faster than the kernel clock. Of course, the kernel clock
0045  *  cannot tick faster than the hardware clock. Therefore, the kernel clock
0046  *  ticks cannot occur more frequently than every 1 millisecond.
0047  */
0048 uint32_t         Clock_isrs;
0049 
0050 /*
0051  *  Records the previous clock ISR (should be NULL)
0052  */
0053 rtems_isr_entry  Old_ticker;
0054 
0055 /*
0056  *  Called when the kernel exits.
0057  */
0058 void clock_exit( void );
0059 
0060 /*
0061  *  VMEchip2_T2_isr
0062  *
0063  *  C ISR Handler. Increment the number of internal ticks. If it is time for a
0064  *  kernel clock tick (if Clock_isrs == 1), call rtems_clock_tick() to signal
0065  *  the event and reset the Clock_isrs counter; else, just decrement it.
0066  */
0067 static rtems_isr VMEchip2_T2_isr(
0068   rtems_vector_number vector
0069 )
0070 {
0071   char overflow;                /* Content of overflow counter */
0072   long i;
0073   long ct;                      /* Number of T2 ticks per RTEMS ticks */
0074 
0075   ct = rtems_configuration_get_microseconds_per_tick() / 1000;
0076 
0077   /*
0078    *  May have missed interrupts, so should look at the overflow counter.
0079    */
0080   lcsr->intr_clear |= 0x02000000;   /* Clear the interrupt */
0081   overflow = (lcsr->board_ctl >> 12) & 0xF;
0082   lcsr->board_ctl |= 0x400;         /* Reset overflow counter */
0083 
0084   /* Attempt to protect against one more period */
0085   if ( overflow == 0 )
0086     overflow = 16;
0087 
0088   Clock_driver_ticks += overflow;   /* One or more internal ticks */
0089 
0090   if ( Clock_isrs <= overflow ) {
0091     /* If its time for kernel clock ticks, signal the events to RTEMS */
0092     for( i = overflow - Clock_isrs; i >= 0; i -= ct ) {
0093       rtems_clock_tick();
0094     }
0095     /* Reset the counter */
0096     Clock_isrs = (uint32_t)-i;
0097   }
0098   else
0099     Clock_isrs -= overflow;
0100 }
0101 
0102 /*
0103  *  VMEchip2_T2_initialize
0104  *
0105  *  Initialize the VMEchip2 Tick Timer #2.
0106  *
0107  *  THE VMECHIP2 PRESCALER REGISTER IS ASSUMED TO BE SET!
0108  *  The prescaler is used by all VMEchip2 timers, including the VMEbus grant
0109  *  timeout counter, the DMAC time off timer, the DMAC timer on timer, and the
0110  *  VMEbus global timeout timer. The prescaler value is normally set by the
0111  *  boot ROM to provide a 1 MHz clock to the timers. For a 25 MHz MVME167, the
0112  *  prescaler value should be 0xE7 (page 2-63).
0113  */
0114 static void VMEchip2_T2_initialize( void )
0115 {
0116   Clock_driver_ticks = 0;
0117   Clock_isrs = rtems_configuration_get_microseconds_per_tick() / 1000;
0118 
0119   lcsr->intr_ena &= 0xFDFFFFFF;   /* Disable tick timer 2 interrupt */
0120   lcsr->intr_clear = 0x02000000;  /* Clear tick timer 2 interrupt */
0121   lcsr->intr_level[0] =           /* Set tick timer 2 interrupt level */
0122       (lcsr->intr_level[0] & 0xFFFFFF0F ) | (CLOCK_INT_LEVEL << 4);
0123   lcsr->timer_cmp_2 = MS_COUNT;   /* Period in compare register */
0124   lcsr->timer_cnt_2 = 0;          /* Clear tick timer 2 counter */
0125   Old_ticker =                    /* Install C ISR */
0126       (rtems_isr_entry) set_vector( VMEchip2_T2_isr, CLOCK_VECTOR, 1 );
0127   lcsr->board_ctl |= 0x700;       /* Start tick timer 2, reset-on-compare, */
0128                                   /*  and clear tick timer 2 overflow counter */
0129   lcsr->intr_ena |= 0x02000000;   /* Enable tick timer 2 interrupt */
0130   lcsr->vector_base |= 0x00800000;/* Unmask VMEchip2 interrupts */
0131   atexit( clock_exit );           /* Turn off T2 interrupts when we exit */
0132 }
0133 
0134 /*
0135  *  This routine stops the VMEchip2 T2 timer, disables its interrupt, and
0136  *  re-install the old interrupt vectors.
0137  */
0138 void clock_exit( void )
0139 {
0140   lcsr->board_ctl &= 0xFFFFFEFF;  /* Stop tick timer 2 */
0141   lcsr->intr_ena &= 0xFDFFFFFF;   /* Disable tick timer 2 interrupt */
0142   lcsr->intr_clear = 0x02000000;  /* Clear tick timer 2 interrupt */
0143 
0144   set_vector( Old_ticker, CLOCK_VECTOR, 1 );
0145 }
0146 
0147 void _Clock_Initialize( void )
0148 {
0149   VMEchip2_T2_initialize();
0150 }