source: rtems/c/src/lib/libbsp/i386/ts_386ex/timer/timer.c @ 7e642ba

4.104.114.84.95
Last change on this file since 7e642ba was 08311cc3, checked in by Joel Sherrill <joel.sherrill@…>, on 11/17/99 at 17:51:34

Updated copyright notice.

  • Property mode set to 100644
File size: 4.8 KB
Line 
1/*  Timer_init()
2 *
3 *  This routine initializes the timer on the FORCE CPU-386 board.
4 *
5 *  Input parameters:  NONE
6 *
7 *  Output parameters:  NONE
8 *
9 *  NOTE: This routine will not work if the optimizer is enabled
10 *        for some compilers.  The multiple writes to the Z8036
11 *        may be optimized away.
12 *
13 *        It is important that the timer start/stop overhead be
14 *        determined when porting or modifying this code.
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 *  $Id$
24 */
25
26
27#include <rtems.h>
28#include <bsp.h>
29#include <stdlib.h>
30
31volatile rtems_unsigned32  Ttimer_val;  /* Updated from ISR!!! */
32rtems_boolean Timer_driver_Find_average_overhead;
33
34extern void timerisr();
35
36/*
37 * Number of us per timer interrupt. Note: 1 us == 1 tick.
38 */
39
40#define  US_PER_ISR   250
41
42void TimerOn(const rtems_raw_irq_connect_data* used)
43{
44
45  Ttimer_val = 0;                           /* clear timer ISR count */
46
47  /* Select timer, stay in mode 0 */
48  outport_byte (TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
49
50  /* Set to 250 usec interval */
51  outport_byte (TIMER_CNTR0, US_PER_ISR & 0xFF );
52  outport_byte (TIMER_CNTR0, (US_PER_ISR >> 8) & 0xFF );
53
54  /* Enable all timers */
55  outport_byte (TIMER_CONFIG, 0x00);
56
57  /*
58   * enable interrrupt at i8259 level
59   */
60  BSP_irq_enable_at_i8259s(used->idtIndex - BSP_IRQ_VECTOR_BASE);
61}
62
63static int TimerIsOn (const rtems_raw_irq_connect_data *used)
64{
65  return BSP_irq_enabled_at_i8259s(used->idtIndex - BSP_IRQ_VECTOR_BASE);
66}
67
68void TimerOff(const rtems_raw_irq_connect_data* used)
69{
70  /* Disable all timers */
71  outport_byte (TIMER_CONFIG, 0x80);
72
73  /*
74   * disable interrrupt at i8259 level
75   */
76  BSP_irq_disable_at_i8259s(used->idtIndex - BSP_IRQ_VECTOR_BASE);
77  /* reset timer mode to standard (DOS) value */
78}
79
80static rtems_raw_irq_connect_data timer_raw_irq_data = {
81  BSP_PERIODIC_TIMER + BSP_IRQ_VECTOR_BASE,
82  timerisr,
83  TimerOn,
84  TimerOff,
85  TimerIsOn
86};
87
88static rtems_raw_irq_connect_data old_raw_irq_data = {
89  BSP_PERIODIC_TIMER + BSP_IRQ_VECTOR_BASE,
90}; 
91
92void Timer_exit()
93{
94 if (!i386_delete_idt_entry(&timer_raw_irq_data)) {
95      printk("Timer_exit:Timer raw handler removal failed\n");
96      rtems_fatal_error_occurred(1);
97 }
98}
99
100void Timer_initialize(void)
101{
102
103  static rtems_boolean First = TRUE;
104
105  if (First)
106  {
107    First = FALSE;
108
109    if (!i386_get_current_idt_entry (&old_raw_irq_data)) {
110      printk("Timer_initialize: failed to get old raw irq entry.\n");
111      rtems_fatal_error_occurred(1);
112    }
113
114    if (!i386_delete_idt_entry (&old_raw_irq_data)) {
115      printk("Timer_initialize: failed to delete old raw irq entry.\n");
116      rtems_fatal_error_occurred(1);
117    }
118
119    atexit(Timer_exit); /* Try not to hose the system at exit. */
120    if (!i386_set_idt_entry (&timer_raw_irq_data)) {
121      printk("Timer_initialize: raw handler installation failed.\n");
122      rtems_fatal_error_occurred(1);
123    }
124  }
125
126  /* wait for ISR to be called at least once */
127  Ttimer_val = 0;
128  while (Ttimer_val == 0)
129    continue;
130  Ttimer_val = 0;
131}
132
133
134#define AVG_OVERHEAD      3  /* It typically takes 3.0 microseconds */
135                             /* (3 ticks) to start/stop the timer. */
136#define LEAST_VALID       4  /* Don't trust a value lower than this */
137
138int Read_timer(void)
139{
140  register rtems_unsigned32 clicks, total;
141  register rtems_unsigned8 lsb, msb;
142
143  /* latch the count */
144  outport_byte (TIMER_MODE, TIMER_SEL0|TIMER_LATCH );
145
146  /* read the count */
147  inport_byte (TIMER_CNTR0, lsb );
148  inport_byte (TIMER_CNTR0, msb );
149
150  /*
151   * Timer ISR increments Ttimer_val every US_PER_ISR clock ticks,
152   * where 1 tick == 1 us. Below, 'click' is in microseconds.
153   *
154   * This assumes the timer input clocks are sourced from the system's
155   * prescaled clock (PSCLK), which is set to be at 1MHz.
156   */
157  clicks = (msb << 8) | lsb;
158  total = Ttimer_val * US_PER_ISR + (US_PER_ISR - clicks);
159
160  if ( Timer_driver_Find_average_overhead == 1 )
161    return total;          /* in one microsecond units */
162  else if ( total < LEAST_VALID )
163    return 0;            /* below timer resolution */
164  else
165    return (total - AVG_OVERHEAD);
166}
167
168rtems_status_code Empty_function( void )
169{
170  return RTEMS_SUCCESSFUL;
171}
172
173void Set_find_average_overhead(
174  rtems_boolean find_flag
175)
176{
177  Timer_driver_Find_average_overhead = find_flag;
178}
179
180/*
181 *  Wait_X_ms: a delay loop used by the network driver...
182 */
183
184#define SLOW_DOWN_IO  0x80      /* I/O port which does nothing */
185#define LOOP1MS        320      /* Just a guess....  */
186
187void Wait_X_ms (unsigned timeToWait)
188{
189  unsigned i, j;
190
191  for (j=0; j<timeToWait; j++)
192    for (i=0; i<LOOP1MS; i++)
193      outport_byte (SLOW_DOWN_IO, 0);
194}
Note: See TracBrowser for help on using the repository browser.