source: rtems/c/src/lib/libbsp/i386/ts_386ex/timer/timer.c @ 0bbd74de

4.104.114.95
Last change on this file since 0bbd74de was 0bbd74de, checked in by Ralf Corsepius <ralf.corsepius@…>, on 09/05/08 at 06:23:37

Convert to "bool".

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