source: rtems/c/src/lib/libcpu/sh/sh7750/timer/timer.c @ b4a45795

4.104.114.84.95
Last change on this file since b4a45795 was ba71076, checked in by Joel Sherrill <joel.sherrill@…>, on 10/12/01 at 13:19:08

2001-10-11 Alexandra Kossovsky <sasha@…>

  • clock/Makefile.am, clock/ckinit.c, clock/.cvsignore, Makefile.am, include/Makefile.am, include/iosh7750.h, include/ipl.h, include/ispsh7750.h, include/sh4_regs.h, include/sh4uart.h, include/sh7750_regs.h, include/.cvsignore, sci/Makefile.am, sci/console.c, sci/sh4uart.c, sci/.cvsignore, score/Makefile.am, score/cpu_asm.c, score/ispsh7750.c, score/.cvsignore, timer/Makefile.am, timer/timer.c, timer/.cvsignore, configure.ac, .cvsignore, ChangeLog?: New files. Reviewed and updated to latest automake and autoconf standards by Ralf Corsepius <corsepiu@…>.
  • Property mode set to 100644
File size: 7.5 KB
Line 
1/*
2 *  timer driver for the Hitachi SH 7750
3 *
4 *  This file manages the benchmark timer used by the RTEMS Timing Test
5 *  Suite.  Each measured time period is demarcated by calls to
6 *  Timer_initialize() and Read_timer().  Read_timer() usually returns
7 *  the number of microseconds since Timer_initialize() exitted.
8 *
9 *  NOTE: It is important that the timer start/stop overhead be
10 *        determined when porting or modifying this code.
11 *
12 *  Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
13 *  Author: Victor V. Vengerov <vvv@oktet.ru>
14 *
15 *  COPYRIGHT (c) 1998.
16 *  On-Line Applications Research Corporation (OAR).
17 *  Copyright assigned to U.S. Government, 1994.
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#include <rtems.h>
27
28#include <rtems/score/sh_io.h>
29#include <rtems/score/iosh7750.h>
30
31#ifndef TIMER_PRIO
32#define TIMER_PRIO 15
33#endif
34
35/* Timer prescaler division ratio */
36#define TIMER_PRESCALER 4
37#define TCR1_TPSC       SH7750_TCR_TPSC_DIV4
38
39#define TIMER_VECTOR SH7750_EVT_TO_NUM(SH7750_EVT_TUNI1)
40
41rtems_isr timerisr();
42
43static rtems_unsigned32 Timer_interrupts;
44
45/* Counter should be divided to this value to obtain time in microseconds */
46static rtems_unsigned32 microseconds_divider;
47
48/* Interrupt period in microseconds */
49static rtems_unsigned32 microseconds_per_int;
50
51rtems_boolean Timer_driver_Find_average_overhead;
52
53/* Timer_initialize --
54 *     Initialize Timer 1 to operate as a RTEMS benchmark timer:
55 *        - determine timer clock frequency
56 *        - install timer interrupt handler
57 *        - configure the Timer 1 hardware
58 *        - start the timer
59 *
60 * PARAMETERS:
61 *     none
62 *
63 * RETURNS:
64 *     none
65 */
66void
67Timer_initialize(void)
68{
69    rtems_unsigned8       temp8;
70    rtems_unsigned16      temp16;
71    rtems_interrupt_level level;
72    rtems_isr            *ignored;
73    int                   cpudiv = 1;
74    int                   tidiv = 1;
75
76    Timer_interrupts  = 0;
77    _CPU_ISR_Disable(level);
78
79    /* Get CPU frequency divider from clock unit */
80    switch (read16(SH7750_FRQCR) & SH7750_FRQCR_IFC)
81    {
82        case SH7750_FRQCR_IFCDIV1:
83            cpudiv = 1;
84            break;
85       
86        case SH7750_FRQCR_IFCDIV2:
87            cpudiv = 2;
88            break;
89           
90        case SH7750_FRQCR_IFCDIV3:
91            cpudiv = 3;
92            break;
93       
94        case SH7750_FRQCR_IFCDIV4:
95            cpudiv = 4;
96            break;
97       
98        case SH7750_FRQCR_IFCDIV6:
99            cpudiv = 6;
100            break;
101       
102        case SH7750_FRQCR_IFCDIV8:
103            cpudiv = 8;
104            break;
105       
106        default:
107            rtems_fatal_error_occurred( RTEMS_NOT_CONFIGURED);
108    }
109
110    /* Get peripheral module frequency divider from clock unit */
111    switch (read16(SH7750_FRQCR) & SH7750_FRQCR_PFC)
112    {
113        case SH7750_FRQCR_PFCDIV2:
114            tidiv = 2 * TIMER_PRESCALER;
115            break;
116           
117        case SH7750_FRQCR_PFCDIV3:
118            tidiv = 3 * TIMER_PRESCALER;
119            break;
120       
121        case SH7750_FRQCR_PFCDIV4:
122            tidiv = 4 * TIMER_PRESCALER;
123            break;
124       
125        case SH7750_FRQCR_PFCDIV6:
126            tidiv = 6 * TIMER_PRESCALER;
127            break;
128       
129        case SH7750_FRQCR_PFCDIV8:
130            tidiv = 8 * TIMER_PRESCALER;
131            break;
132       
133        default:
134            rtems_fatal_error_occurred( RTEMS_NOT_CONFIGURED);
135    }
136
137    microseconds_divider =
138        rtems_cpu_configuration_get_clicks_per_second() * cpudiv /
139        (tidiv * 1000000);
140    microseconds_per_int = 0xFFFFFFFF / microseconds_divider;
141
142    /*
143     *  Hardware specific initialization
144     */
145
146    /* Stop the Timer 0 */
147    temp8 = read8(SH7750_TSTR);
148    temp8 &= ~SH7750_TSTR_STR1;
149    write8(temp8, SH7750_TSTR);
150
151    /* Establish interrupt handler */
152    _CPU_ISR_install_raw_handler( TIMER_VECTOR, timerisr, &ignored );
153
154    /* Reset timer constant and counter */
155    write32(0xFFFFFFFF, SH7750_TCOR1);
156    write32(0xFFFFFFFF, SH7750_TCNT1);
157   
158    /* Select timer mode */
159    write16(
160        SH7750_TCR_UNIE |        /* Enable Underflow Interrupt */
161        SH7750_TCR_CKEG_RAISE |  /* Count on rising edge */
162        TCR1_TPSC,               /* Timer prescaler ratio */
163        SH7750_TCR1);
164
165    /* Set timer interrupt priority */
166    temp16 = read16(SH7750_IPRA);
167    temp16 = (temp16 & ~SH7750_IPRA_TMU1) | (TIMER_PRIO << SH7750_IPRA_TMU1_S);
168    write16(temp16, SH7750_IPRA);
169
170
171    _CPU_ISR_Enable(level);
172
173    /* Start the Timer 1 */
174    temp8 = read8(SH7750_TSTR);
175    temp8 |= SH7750_TSTR_STR1;
176    write8(temp8, SH7750_TSTR);
177
178}
179
180/*
181 *  The following controls the behavior of Read_timer().
182 *
183 *  AVG_OVERHEAD is the overhead for starting and stopping the timer.  It
184 *  is usually deducted from the number returned.
185 *
186 *  LEAST_VALID is the lowest number this routine should trust.  Numbers
187 *  below this are "noise" and zero is returned.
188 */
189
190#define AVG_OVERHEAD      0  /* It typically takes X.X microseconds */
191                             /* (Y countdowns) to start/stop the timer. */
192                             /* This value is in microseconds. */
193#define LEAST_VALID       0 /* 20 */ /* Don't trust a clicks value lower than this */
194
195/* Read_timer --
196 *     Read timer value in microsecond units since timer start.
197 *
198 * PARAMETERS:
199 *     none
200 *
201 * RETURNS:
202 *     number of microseconds since timer has been started
203 */
204int
205Read_timer(void)
206{
207    rtems_unsigned32 clicks;
208    rtems_unsigned32 ints;
209    rtems_unsigned32 total ;
210    rtems_interrupt_level level;
211    rtems_unsigned32 tcr;
212   
213
214    _CPU_ISR_Disable(level);
215
216    clicks = 0xFFFFFFFF - read32(SH7750_TCNT1);
217    tcr = read32(SH7750_TCR1);
218    ints = Timer_interrupts;
219   
220    _CPU_ISR_Enable(level);
221   
222    /* Handle the case when timer overflowed but interrupt was not processed */
223    if ((clicks > 0xFF000000) && ((tcr & SH7750_TCR_UNF) != 0))
224    {
225        ints++;
226    }
227
228    total = microseconds_per_int * ints + (clicks / microseconds_divider);
229
230    if ( Timer_driver_Find_average_overhead )
231        return total;          /* in microsecond units */
232    else
233    {
234        if ( total < LEAST_VALID )
235            return 0;            /* below timer resolution */
236        /*
237         *  Somehow convert total into microseconds
238         */
239        return (total - AVG_OVERHEAD) ;
240    }
241}
242
243/* Empty_function --
244 *     Empty function call used in loops to measure basic cost of looping
245 *     in Timing Test Suite.
246 *
247 * PARAMETERS:
248 *     none
249 *
250 * RETURNS:
251 *     RTEMS_SUCCESSFUL
252 */
253rtems_status_code
254Empty_function( void )
255{
256  return RTEMS_SUCCESSFUL;
257}
258
259/* Set_find_average_overhead --
260 *     This routine is invoked by the "Check Timer" (tmck) test in the
261 *     RTEMS Timing Test Suite. It makes the Read_timer routine not
262 *     subtract the overhead required to initialize and read the benchmark
263 *     timer.
264 *
265 * PARAMETERS:
266 *     find_flag - boolean flag, TRUE if overhead must not be subtracted.
267 *
268 * RETURNS:
269 *     none
270 */
271void
272Set_find_average_overhead(rtems_boolean find_flag)
273{
274    Timer_driver_Find_average_overhead = find_flag;
275}
276
277/* timerisr --
278 *     Timer interrupt handler routine. This function invoked on timer
279 *     underflow event; once per 2^32 clocks. It should reset the timer
280 *     event and increment timer interrupts counter.
281 */
282void
283timerisr(void)
284{
285  unsigned8 temp8;
286
287  /* reset the flags of the status register */
288  temp8 = read8(SH7750_TCR1) & ~SH7750_TCR_UNF;
289  write8(temp8, SH7750_TCR1);
290
291  Timer_interrupts += 1;
292}
Note: See TracBrowser for help on using the repository browser.