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

4.104.114.84.95
Last change on this file since 60b791ad was 60b791ad, checked in by Joel Sherrill <joel.sherrill@…>, on 02/17/98 at 23:46:28

updated copyright to 1998

  • Property mode set to 100644
File size: 9.0 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 TIMER_IRQ     0x00           /* Timer IRQ.                            */
47#define AVG_OVERHEAD  0              /* 0.1 microseconds to start/stop timer. */
48#define LEAST_VALID   1              /* Don't trust a value lower than this.  */
49
50/*-------------------------------------------------------------------------+
51| Global Variables
52+--------------------------------------------------------------------------*/
53volatile rtems_unsigned32 Ttimer_val;
54         rtems_boolean    Timer_driver_Find_average_overhead = TRUE;
55
56/*-------------------------------------------------------------------------+
57| Pentium optimized timer handling.
58+--------------------------------------------------------------------------*/
59#if defined(pentium)
60
61/*-------------------------------------------------------------------------+
62|         Function: rdtsc
63|      Description: Read the value of PENTIUM on-chip cycle counter.
64| Global Variables: None.
65|        Arguments: None.
66|          Returns: Value of PENTIUM on-chip cycle counter.
67+--------------------------------------------------------------------------*/
68static inline unsigned long long
69rdtsc(void)
70{
71  /* Return the value of the on-chip cycle counter. */
72  unsigned long long result;
73  asm volatile(".byte 0x0F, 0x31" : "=A" (result));
74  return result;
75} /* rdtsc */
76
77
78/*-------------------------------------------------------------------------+
79|         Function: Timer_exit
80|      Description: Timer cleanup routine at RTEMS exit. NOTE: This routine is
81|                   not really necessary, since there will be a reset at exit.
82| Global Variables: None.
83|        Arguments: None.
84|          Returns: Nothing.
85+--------------------------------------------------------------------------*/
86void
87Timer_exit(void)
88{
89  PC386_disableIrq(TIMER_IRQ);
90} /* Timer_exit */
91
92
93/*-------------------------------------------------------------------------+
94|         Function: Timer_initialize
95|      Description: Timer initialization routine.
96| Global Variables: Ttimer_val.
97|        Arguments: None.
98|          Returns: Nothing.
99+--------------------------------------------------------------------------*/
100void
101Timer_initialize(void)
102{
103  static rtems_boolean First = TRUE;
104
105  if (First)
106  {
107    First = FALSE;
108
109    atexit(Timer_exit); /* Try not to hose the system at exit. */
110    PC386_enableIrq(TIMER_IRQ);
111                  /* Disable the programmable timer so ticks don't interfere. */
112  }
113  Ttimer_val = rdtsc(); /* read starting time */
114} /* Timer_initialize */
115
116
117/*-------------------------------------------------------------------------+
118|         Function: Read_timer
119|      Description: Read hardware timer value.
120| Global Variables: Ttimer_val, Timer_driver_Find_average_overhead.
121|        Arguments: None.
122|          Returns: Nothing.
123+--------------------------------------------------------------------------*/
124rtems_unsigned32
125Read_timer(void)
126{
127  register rtems_unsigned32 total;
128
129  total =  (rtems_unsigned32)(rdtsc() - Ttimer_val);
130
131  if (Timer_driver_Find_average_overhead)
132    return total;
133  else if (total < LEAST_VALID)
134    return 0; /* below timer resolution */
135  else
136    return (total - AVG_OVERHEAD);
137} /* Read_timer */
138
139#else /* pentium */
140
141/*-------------------------------------------------------------------------+
142| Non-Pentium timer handling.
143+--------------------------------------------------------------------------*/
144#define US_PER_ISR   250  /* Number of micro-seconds per timer interruption */
145
146/*-------------------------------------------------------------------------+
147| External Prototypes
148+--------------------------------------------------------------------------*/
149extern rtems_isr timerisr(rtems_vector_number);
150       /* timer (int 08h) Interrupt Service Routine (defined in 'timerisr.s') */
151
152/*-------------------------------------------------------------------------+
153|         Function: Timer_exit
154|      Description: Timer cleanup routine at RTEMS exit. NOTE: This routine is
155|                   not really necessary, since there will be a reset at exit.
156| Global Variables: None.
157|        Arguments: None.
158|          Returns: Nothing.
159+--------------------------------------------------------------------------*/
160void
161Timer_exit(void)
162{
163  /* reset timer mode to standard (DOS) value */
164  outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
165  outport_byte(TIMER_CNTR0, 0);
166  outport_byte(TIMER_CNTR0, 0);
167} /* Timer_exit */
168
169
170/*-------------------------------------------------------------------------+
171|         Function: Timer_initialize
172|      Description: Timer initialization routine.
173| Global Variables: Ttimer_val.
174|        Arguments: None.
175|          Returns: Nothing.
176+--------------------------------------------------------------------------*/
177void
178Timer_initialize(void)
179{
180  static rtems_boolean First = TRUE;
181
182  if (First)
183  {
184    First = FALSE;
185
186    atexit(Timer_exit); /* Try not to hose the system at exit. */
187
188    /* install a raw interrupt handler for timer */
189    PC386_installRawIrqHandler(TIMER_IRQ, timerisr);
190
191    /* load timer for US_PER_ISR microsecond period */
192    outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
193    outport_byte(TIMER_CNTR0, US_TO_TICK(US_PER_ISR) >> 0 & 0xff);
194    outport_byte(TIMER_CNTR0, US_TO_TICK(US_PER_ISR) >> 8 & 0xff);
195  }
196  /* wait for ISR to be called at least once */
197  Ttimer_val = 0;
198  while (Ttimer_val == 0)
199    continue;
200  Ttimer_val = 0;
201} /* Timer_initialize */
202
203
204/*-------------------------------------------------------------------------+
205|         Function: Read_timer
206|      Description: Read hardware timer value.
207| Global Variables: Ttimer_val, Timer_driver_Find_average_overhead.
208|        Arguments: None.
209|          Returns: Nothing.
210+--------------------------------------------------------------------------*/
211rtems_unsigned32
212Read_timer(void)
213{
214  register rtems_unsigned32 total, clicks;
215  register rtems_unsigned8  lsb, msb;
216
217  outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_LATCH);
218  inport_byte(TIMER_CNTR0, lsb);
219  inport_byte(TIMER_CNTR0, msb);
220  clicks = (msb << 8) | lsb;
221  total  = (Ttimer_val * US_PER_ISR) + (US_PER_ISR - TICK_TO_US(clicks));
222
223  if (Timer_driver_Find_average_overhead)
224    return total;
225  else if (total < LEAST_VALID)
226    return 0; /* below timer resolution */
227  else
228    return (total - AVG_OVERHEAD);
229}
230
231#endif /* pentium */
232
233
234/*-------------------------------------------------------------------------+
235|         Function: Empty_function
236|      Description: Empty function used in time tests.
237| Global Variables: None.
238|        Arguments: None.
239|          Returns: Nothing.
240+--------------------------------------------------------------------------*/
241rtems_status_code Empty_function(void)
242{
243  return RTEMS_SUCCESSFUL;
244} /* Empty function */
245 
246
247/*-------------------------------------------------------------------------+
248|         Function: Set_find_average_overhead
249|      Description: Set internal Timer_driver_Find_average_overhead flag value.
250| Global Variables: Timer_driver_Find_average_overhead.
251|        Arguments: find_flag - new value of the flag.
252|          Returns: Nothing.
253+--------------------------------------------------------------------------*/
254void
255Set_find_average_overhead(rtems_boolean find_flag)
256{
257  Timer_driver_Find_average_overhead = find_flag;
258} /* Set_find_average_overhead */
Note: See TracBrowser for help on using the repository browser.