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

4.104.114.84.95
Last change on this file since 7150f00f was 7150f00f, checked in by Joel Sherrill <joel.sherrill@…>, on Dec 1, 1997 at 10:06:48 PM

Inclusion of PC386 BSP submitted by Pedro Miguel Da Cruz Neto Romano
<pmcnr@…> and Jose Rufino <ruf@…>
of NavIST (http://pandora.ist.utl.pt/).

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