source: rtems/c/src/lib/libbsp/i386/pc386/timer/timer.c @ bd8c8b2a

4.104.114.84.9
Last change on this file since bd8c8b2a was bd8c8b2a, checked in by Joel Sherrill <joel.sherrill@…>, on Aug 5, 1998 at 4:51:39 PM

Patch from Eric Valette <valette@…> which brings the i386ex BSP
inline with the new IRQ structure.

  • Property mode set to 100644
File size: 9.8 KB
Line 
1/*-------------------------------------------------------------------------+
2| timer.c v1.1 - PC386 BSP - 1997/08/07
3+--------------------------------------------------------------------------+
4| This file contains the PC386 timer package.
5+--------------------------------------------------------------------------+
6| NOTE: It is important that the timer start/stop overhead be determined
7|       when porting or modifying this code.
8+--------------------------------------------------------------------------+
9| (C) Copyright 1997 -
10| - NavIST Group - Real-Time Distributed Systems and Industrial Automation
11|
12| http://pandora.ist.utl.pt
13|
14| Instituto Superior Tecnico * Lisboa * PORTUGAL
15+--------------------------------------------------------------------------+
16| Disclaimer:
17|
18| This file is provided "AS IS" without warranty of any kind, either
19| expressed or implied.
20+--------------------------------------------------------------------------+
21| This code is base on:
22|   timer.c,v 1.7 1995/12/19 20:07:43 joel Exp - go32 BSP
23| With the following copyright notice:
24| **************************************************************************
25| *  COPYRIGHT (c) 1989-1998.
26| *  On-Line Applications Research Corporation (OAR).
27| *  Copyright assigned to U.S. Government, 1994.
28| *
29| *  The license and distribution terms for this file may be
30| *  found in found in the file LICENSE in this distribution or at
31| *  http://www.OARcorp.com/rtems/license.html.
32| **************************************************************************
33|
34|  $Id$
35+--------------------------------------------------------------------------*/
36
37
38#include <stdlib.h>
39
40#include <bsp.h>
41#include <irq.h>
42
43/*-------------------------------------------------------------------------+
44| Constants
45+--------------------------------------------------------------------------*/
46#define AVG_OVERHEAD  0              /* 0.1 microseconds to start/stop timer. */
47#define LEAST_VALID   1              /* Don't trust a value lower than this.  */
48
49/*-------------------------------------------------------------------------+
50| Global Variables
51+--------------------------------------------------------------------------*/
52volatile rtems_unsigned32 Ttimer_val;
53         rtems_boolean    Timer_driver_Find_average_overhead = TRUE;
54
55/*-------------------------------------------------------------------------+
56| External Prototypes
57+--------------------------------------------------------------------------*/
58extern void timerisr();
59       /* timer (int 08h) Interrupt Service Routine (defined in 'timerisr.s') */
60extern int clockIsOn(const rtems_irq_connect_data*);
61
62/*-------------------------------------------------------------------------+
63| Pentium optimized timer handling.
64+--------------------------------------------------------------------------*/
65#if defined(pentium)
66
67/*-------------------------------------------------------------------------+
68|         Function: rdtsc
69|      Description: Read the value of PENTIUM on-chip cycle counter.
70| Global Variables: None.
71|        Arguments: None.
72|          Returns: Value of PENTIUM on-chip cycle counter.
73+--------------------------------------------------------------------------*/
74static inline unsigned long long
75rdtsc(void)
76{
77  /* Return the value of the on-chip cycle counter. */
78  unsigned long long result;
79  asm volatile(".byte 0x0F, 0x31" : "=A" (result));
80  return result;
81} /* rdtsc */
82
83
84/*-------------------------------------------------------------------------+
85|         Function: Timer_exit
86|      Description: Timer cleanup routine at RTEMS exit. NOTE: This routine is
87|                   not really necessary, since there will be a reset at exit.
88| Global Variables: None.
89|        Arguments: None.
90|          Returns: Nothing.
91+--------------------------------------------------------------------------*/
92void
93Timer_exit(void)
94{
95} /* Timer_exit */
96
97
98/*-------------------------------------------------------------------------+
99|         Function: Timer_initialize
100|      Description: Timer initialization routine.
101| Global Variables: Ttimer_val.
102|        Arguments: None.
103|          Returns: Nothing.
104+--------------------------------------------------------------------------*/
105void
106Timer_initialize(void)
107{
108  static rtems_boolean First = TRUE;
109
110  if (First)
111  {
112    First = FALSE;
113
114    atexit(Timer_exit); /* Try not to hose the system at exit. */
115  }
116  Ttimer_val = rdtsc(); /* read starting time */
117} /* Timer_initialize */
118
119
120/*-------------------------------------------------------------------------+
121|         Function: Read_timer
122|      Description: Read hardware timer value.
123| Global Variables: Ttimer_val, Timer_driver_Find_average_overhead.
124|        Arguments: None.
125|          Returns: Nothing.
126+--------------------------------------------------------------------------*/
127rtems_unsigned32
128Read_timer(void)
129{
130  register rtems_unsigned32 total;
131
132  total =  (rtems_unsigned32)(rdtsc() - Ttimer_val);
133
134  if (Timer_driver_Find_average_overhead)
135    return total;
136  else if (total < LEAST_VALID)
137    return 0; /* below timer resolution */
138  else
139    return (total - AVG_OVERHEAD);
140} /* Read_timer */
141
142#else /* pentium */
143
144/*-------------------------------------------------------------------------+
145| Non-Pentium timer handling.
146+--------------------------------------------------------------------------*/
147#define US_PER_ISR   250  /* Number of micro-seconds per timer interruption */
148
149
150/*-------------------------------------------------------------------------+
151|         Function: Timer_exit
152|      Description: Timer cleanup routine at RTEMS exit. NOTE: This routine is
153|                   not really necessary, since there will be a reset at exit.
154| Global Variables: None.
155|        Arguments: None.
156|          Returns: Nothing.
157+--------------------------------------------------------------------------*/
158void
159timerOff(const rtems_raw_irq_connect_data* used)
160{
161    /*
162     * disable interrrupt at i8259 level
163     */
164     pc386_irq_disable_at_i8259s(used->idtIndex - PC386_IRQ_VECTOR_BASE);
165     /* reset timer mode to standard (DOS) value */
166     outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
167     outport_byte(TIMER_CNTR0, 0);
168     outport_byte(TIMER_CNTR0, 0);
169} /* Timer_exit */
170
171
172void timerOn(const rtems_raw_irq_connect_data* used)
173{
174     /* load timer for US_PER_ISR microsecond period */
175     outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
176     outport_byte(TIMER_CNTR0, US_TO_TICK(US_PER_ISR) >> 0 & 0xff);
177     outport_byte(TIMER_CNTR0, US_TO_TICK(US_PER_ISR) >> 8 & 0xff);
178    /*
179     * enable interrrupt at i8259 level
180     */
181     pc386_irq_enable_at_i8259s(used->idtIndex - PC386_IRQ_VECTOR_BASE);
182}
183
184static rtems_raw_irq_connect_data timer_raw_irq_data = {
185  PC_386_PERIODIC_TIMER + PC386_IRQ_VECTOR_BASE,
186  timerisr,
187  timerOn,
188  timerOff,
189  clockIsOn
190};
191
192/*-------------------------------------------------------------------------+
193|         Function: Timer_exit
194|      Description: Timer cleanup routine at RTEMS exit. NOTE: This routine is
195|                   not really necessary, since there will be a reset at exit.
196| Global Variables: None.
197|        Arguments: None.
198|          Returns: Nothing.
199+--------------------------------------------------------------------------*/
200void
201Timer_exit(void)
202{
203  i386_delete_idt_entry (&timer_raw_irq_data);
204} /* Timer_exit */
205
206/*-------------------------------------------------------------------------+
207|         Function: Timer_initialize
208|      Description: Timer initialization routine.
209| Global Variables: Ttimer_val.
210|        Arguments: None.
211|          Returns: Nothing.
212+--------------------------------------------------------------------------*/
213void
214Timer_initialize(void)
215{
216  static rtems_boolean First = TRUE;
217
218  if (First)
219  {
220    First = FALSE;
221
222    atexit(Timer_exit); /* Try not to hose the system at exit. */
223    if (!i386_set_idt_entry (&timer_raw_irq_data)) {
224      printk("raw handler connexion failed\n");
225      rtems_fatal_error_occurred(1);
226    }
227  }
228  /* wait for ISR to be called at least once */
229  Ttimer_val = 0;
230  while (Ttimer_val == 0)
231    continue;
232  Ttimer_val = 0;
233} /* Timer_initialize */
234
235
236/*-------------------------------------------------------------------------+
237|         Function: Read_timer
238|      Description: Read hardware timer value.
239| Global Variables: Ttimer_val, Timer_driver_Find_average_overhead.
240|        Arguments: None.
241|          Returns: Nothing.
242+--------------------------------------------------------------------------*/
243rtems_unsigned32
244Read_timer(void)
245{
246  register rtems_unsigned32 total, clicks;
247  register rtems_unsigned8  lsb, msb;
248
249  outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_LATCH);
250  inport_byte(TIMER_CNTR0, lsb);
251  inport_byte(TIMER_CNTR0, msb);
252  clicks = (msb << 8) | lsb;
253  total  = (Ttimer_val * US_PER_ISR) + (US_PER_ISR - TICK_TO_US(clicks));
254
255  if (Timer_driver_Find_average_overhead)
256    return total;
257  else if (total < LEAST_VALID)
258    return 0; /* below timer resolution */
259  else
260    return (total - AVG_OVERHEAD);
261}
262
263#endif /* pentium */
264
265
266/*-------------------------------------------------------------------------+
267|         Function: Empty_function
268|      Description: Empty function used in time tests.
269| Global Variables: None.
270|        Arguments: None.
271|          Returns: Nothing.
272+--------------------------------------------------------------------------*/
273rtems_status_code Empty_function(void)
274{
275  return RTEMS_SUCCESSFUL;
276} /* Empty function */
277 
278
279/*-------------------------------------------------------------------------+
280|         Function: Set_find_average_overhead
281|      Description: Set internal Timer_driver_Find_average_overhead flag value.
282| Global Variables: Timer_driver_Find_average_overhead.
283|        Arguments: find_flag - new value of the flag.
284|          Returns: Nothing.
285+--------------------------------------------------------------------------*/
286void
287Set_find_average_overhead(rtems_boolean find_flag)
288{
289  Timer_driver_Find_average_overhead = find_flag;
290} /* Set_find_average_overhead */
Note: See TracBrowser for help on using the repository browser.