source: rtems/c/src/lib/libbsp/m68k/mvme167/clock/ckinit.c @ 0dd1d44

4.104.114.84.95
Last change on this file since 0dd1d44 was 0dd1d44, checked in by Joel Sherrill <joel.sherrill@…>, on Jan 11, 2000 at 5:34:20 PM

Removed old hack of using Configuration Table entry ticks_per_timeslice
being set to 0 to indicate that there should be no Clock Tick. This
was used by the Timing Tests to avoid clock tick overhead perturbing
execution times. Now the Timing Tests simply leave the Clock Tick
Driver out of the Device Driver Table.

  • Property mode set to 100644
File size: 8.4 KB
Line 
1/*  ckinit.c
2 *
3 *  Implementation of the Clock_control() and Clock_initialize() functions
4 *  prototyped in rtems/c/src/lib/include/clockdrv.h.
5 *
6 *  This port does not allow the application to select which timer on the
7 *  MVME167 to use for the clock, nor does it allow the application to
8 *  configure the clock. The clock uses the VMEchip2 Tick Timer #2. This
9 *  timer is set up to raise a MC680x0 level-6 interrupt every 1 ms. The
10 *  interrupt vector is 0x69.
11 *
12 *  All page references are to the MVME166/MVME167/MVME187 Single Board
13 *  Computer Programmer's Reference Guide (MVME187PG/D2) with the April
14 *  1993 supplements/addenda (MVME187PG/D2A1).
15 *
16 *  COPYRIGHT (c) 1989-1999.
17 *  On-Line Applications Research Corporation (OAR).
18 *
19 *  The license and distribution terms for this file may be
20 *  found in the file LICENSE in this distribution or at
21 *  http://www.OARcorp.com/rtems/license.html.
22 *
23 *  Modifications of respective RTEMS files:
24 *  Copyright (c) 1998, National Research Council of Canada
25 *
26 *  $Id$
27 */
28 
29#include <stdlib.h>
30#include <bsp.h>
31#include <rtems/libio.h>
32
33#define MS_COUNT          1000              /* T2's countdown constant (1 ms) */
34#define CLOCK_INT_LEVEL   6                 /* T2's interrupt level */
35#define CLOCK_VECTOR (VBR0 * 0x10 + 0x9)    /* T2 is vector $X9 (p. 2-71)*/
36
37/*
38 *  These are declared in rtems/c/src/lib/include/clockdrv.h
39 *  In other BSPs, rtems_clock_major is set to the largest possible value
40 *  (which is almost certainly greater than the number of I/O devices) to
41 *  indicate that this device has not been initialized yet. The actual
42 *  device number is supplied during initialization. We do not do that.
43 *
44 *  Initialized data ends up the the .data section. This causes two problems:
45 *  1) the .data section is no longer ROMable because we need to write into
46 *  it. 2) The initial value is correct only after a download. On subsequent
47 *  program restarts, the value is not re-initialized but left to whatever it
48 *  was when the previous run terminated or aborted. If we depend on some
49 *  global variable value, we must initialize that value explicitly in code
50 *  at boot time.
51 */
52rtems_device_major_number rtems_clock_major;
53rtems_device_minor_number rtems_clock_minor;
54
55/*
56 *  Clock_driver_ticks is a monotonically increasing counter of the number of
57 *  VMEchip2 timer #2 ticks since the driver was initialized.
58 */
59volatile rtems_unsigned32 Clock_driver_ticks;
60
61
62/*
63 *  Clock_isrs is the number of clock ISRs until the next invocation of the
64 *  RTEMS clock tick routine. This clock tick device driver gets an interrupt
65 *  once a millisecond and counts down until the length of time between the
66 *  user configured microseconds per tick has passed. This allows the clock
67 *  device to "tick" faster than the kernel clock. Of course, the kernel clock
68 *  cannot tick faster than the hardware clock. Therefore, the kernel clock
69 *  ticks cannot occur more frequently than every 1 millisecond.
70 */
71rtems_unsigned32 Clock_isrs;
72
73
74/*
75 *  Records the previous clock ISR (should be NULL)
76 */
77rtems_isr_entry  Old_ticker;
78
79
80/*
81 *  Called when the kernel exits.
82 */
83void clock_exit( void );
84
85
86/*
87 *  VMEchip2_T2_isr
88 *
89 *  C ISR Handler. Increment the number of internal ticks. If it is time for a
90 *  kernel clock tick (if Clock_isrs == 1), call rtems_clock_tick() to signal
91 *  the event and reset the Clock_isrs counter; else, just decrement it.
92 *
93 *  Input parameters:
94 *    vector number
95 *
96 *  Output parameters: NONE
97 *
98 *  Return values: NONE
99 */
100rtems_isr VMEchip2_T2_isr(
101  rtems_vector_number vector
102)
103{
104  char overflow;                /* Content of overflow counter */
105  long i;
106  long ct;                      /* Number of T2 ticks per RTEMS ticks */
107 
108  ct = BSP_Configuration.microseconds_per_tick / 1000;
109 
110  /*
111   *  May have missed interrupts, so should look at the overflow counter.
112   */
113  lcsr->intr_clear |= 0x02000000;   /* Clear the interrupt */
114  overflow = (lcsr->board_ctl >> 12) & 0xF;
115  lcsr->board_ctl |= 0x400;         /* Reset overflow counter */
116 
117  /* Attempt to protect against one more period */
118  if ( overflow == 0 )
119    overflow = 16;
120
121  Clock_driver_ticks += overflow;   /* One or more internal ticks */
122
123  if ( Clock_isrs <= overflow ) {
124    /* If its time for kernel clock ticks, signal the events to RTEMS */
125    for( i = overflow - Clock_isrs; i >= 0; i -= ct ) {
126      rtems_clock_tick();
127    }
128    /* Reset the counter */
129    Clock_isrs = (rtems_unsigned32)-i;
130  }
131  else 
132    Clock_isrs -= overflow;
133}
134
135
136/*
137 *  VMEchip2_T2_initialize
138 *
139 *  Initialize the VMEchip2 Tick Timer #2.
140 *
141 *  THE VMECHIP2 PRESCALER REGISTER IS ASSUMED TO BE SET!
142 *  The prescaler is used by all VMEchip2 timers, including the VMEbus grant
143 *  timeout counter, the DMAC time off timer, the DMAC timer on timer, and the
144 *  VMEbus global timeout timer. The prescaler value is normally set by the
145 *  boot ROM to provide a 1 MHz clock to the timers. For a 25 MHz MVME167, the
146 *  prescaler value should be 0xE7 (page 2-63).
147 *
148 *  Input parameters: NONE
149 *
150 *  Output paremeters: NONE
151 *
152 *  Return values: NONE
153 */
154void VMEchip2_T2_initialize( void )
155{
156  Clock_driver_ticks = 0;
157  Clock_isrs = BSP_Configuration.microseconds_per_tick / 1000;
158
159  lcsr->intr_ena &= 0xFDFFFFFF;   /* Disable tick timer 2 interrupt */
160  lcsr->intr_clear = 0x02000000;  /* Clear tick timer 2 interrupt */
161  lcsr->intr_level[0] =           /* Set tick timer 2 interrupt level */
162      (lcsr->intr_level[0] & 0xFFFFFF0F ) | (CLOCK_INT_LEVEL << 4);
163  lcsr->timer_cmp_2 = MS_COUNT;   /* Period in compare register */
164  lcsr->timer_cnt_2 = 0;          /* Clear tick timer 2 counter */
165  Old_ticker =                    /* Install C ISR */
166      (rtems_isr_entry) set_vector( VMEchip2_T2_isr, CLOCK_VECTOR, 1 );
167  lcsr->board_ctl |= 0x700;       /* Start tick timer 2, reset-on-compare, */
168                                  /*  and clear tick timer 2 overflow counter */
169  lcsr->intr_ena |= 0x02000000;   /* Enable tick timer 2 interrupt */
170  lcsr->vector_base |= 0x00800000;/* Unmask VMEchip2 interrupts */
171  atexit( clock_exit );           /* Turn off T2 interrupts when we exit */
172}
173
174
175/*
176 *  clock_exit
177 *
178 *  This routine stops the VMEchip2 T2 timer, disables its interrupt, and
179 *  re-install the old interrupt vectors.
180 *
181 *  Input parameters:   NONE
182 *
183 *  Output parameters:  NONE
184 *
185 *  Return values:      NONE
186 *
187 */
188void clock_exit( void )
189{
190  lcsr->board_ctl &= 0xFFFFFEFF;  /* Stop tick timer 2 */
191  lcsr->intr_ena &= 0xFDFFFFFF;   /* Disable tick timer 2 interrupt */
192  lcsr->intr_clear = 0x02000000;  /* Clear tick timer 2 interrupt */
193
194  set_vector( Old_ticker, CLOCK_VECTOR, 1 );
195}
196
197
198/*
199 *  Clock_initialize()
200 *  prototyped in rtems/c/src/lib/include/clockdrv.h.
201 *
202 *  Input parameters:
203 *     major - console device major number
204 *     minor - console device minor number
205 *             ALWAYS 0 IN VERSION 3.6.0 OF RTEMS!
206 *             Probably provided for symmetry with the other I/O calls.
207 *     arg   - pointer to optional device driver arguments
208 *             ALWAYS NULL IN VERSION 3.6.0 OF RTEMS!
209 *
210 *  Output paremeters: NONE
211 *
212 *  Return values:
213 *     rtems_device_driver status code
214 */ 
215rtems_device_driver Clock_initialize(
216  rtems_device_major_number major,
217  rtems_device_minor_number minor,
218  void *pargp
219)
220{
221  VMEchip2_T2_initialize();
222 
223  /*
224   *  Make major/minor avail to others such as shared memory driver
225   */
226  rtems_clock_major = major;
227  rtems_clock_minor = minor;
228 
229  return RTEMS_SUCCESSFUL;
230}
231
232
233/*
234 *  Clock_control().
235 *  Prototyped in rtems/c/src/lib/include/clockdrv.h
236 *
237 *  Input parameters:
238 *    major - clock device major number
239 *    minor - clock device minor number
240 *    parg  - pointer to optional device driver arguments
241 *
242 *  Output parameters:  NONE
243 *
244 *  Return values:
245 *    rtems_device_driver status code
246 */
247rtems_device_driver Clock_control(
248  rtems_device_major_number major,
249  rtems_device_minor_number minor,
250  void *pargp)
251{
252    rtems_unsigned32 isrlevel;
253    rtems_libio_ioctl_args_t *args = pargp;
254 
255    if ( args == 0 )
256        goto done;
257 
258    /*
259     * This is hokey, but until we get a defined interface
260     * to do this, it will just be this simple...
261     */
262    if ( args->command == rtems_build_name('I', 'S', 'R', ' ') )
263    {
264      VMEchip2_T2_isr( CLOCK_VECTOR );
265    }
266    else if ( args->command == rtems_build_name('N', 'E', 'W', ' ') )
267    {
268      rtems_interrupt_disable( isrlevel );
269      set_vector( args->buffer, CLOCK_VECTOR, 1 );
270      rtems_interrupt_enable( isrlevel );
271    }
272 
273done:
274    return RTEMS_SUCCESSFUL;
275}
276
Note: See TracBrowser for help on using the repository browser.