source: rtems/c/src/lib/libcpu/sh/sh7045/timer/timer.c @ a5fb3d1b

4.104.115
Last change on this file since a5fb3d1b was 3942cce, checked in by Ralf Corsepius <ralf.corsepius@…>, on 09/05/08 at 12:11:47

Convert to "bool".

  • Property mode set to 100644
File size: 5.0 KB
Line 
1/*
2 *  timer for the Hitachi SH 704X
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 *  benchmark_timer_initialize() and benchmark_timer_read().  benchmark_timer_read() usually returns
7 *  the number of microseconds since benchmark_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 *  Authors: Ralf Corsepius (corsepiu@faw.uni-ulm.de) and
13 *           Bernd Becker (becker@faw.uni-ulm.de)
14 *
15 *  COPYRIGHT (c) 1997-1998, FAW Ulm, Germany
16 *
17 *  This program is distributed in the hope that it will be useful,
18 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20 *
21 *  COPYRIGHT (c) 1998.
22 *  On-Line Applications Research Corporation (OAR).
23 *
24 *  The license and distribution terms for this file may be
25 *  found in the file LICENSE in this distribution or at
26 *  http://www.rtems.com/license/LICENSE.
27 *
28 *  $Id$
29 */
30
31#include <rtems.h>
32
33#include <rtems/score/sh_io.h>
34#include <rtems/score/iosh7045.h>
35
36extern uint32_t bsp_clicks_per_second;
37
38/*
39 *  We use a Phi/4 timer
40 */
41#define SCALE (Timer_MHZ/4)
42
43#define MTU1_STARTMASK  0xfd
44#define MTU1_SYNCMASK   0xfd
45#define MTU1_MODEMASK   0xc0
46#define MTU1_TCRMASK    0x01
47#define MTU1_TIORMASK   0x88
48#define MTU1_STAT_MASK  0xf8
49#define MTU1_TIERMASK   0xfc
50#define IPRC_MTU1_MASK  0xfff0
51
52#ifndef MTU1_PRIO
53#define MTU1_PRIO 15
54#endif
55
56#define MTU1_VECTOR 86
57
58extern rtems_isr timerisr(void);
59
60static uint32_t   Timer_interrupts;
61
62bool benchmark_timer_find_average_overhead;
63
64static uint32_t   Timer_MHZ ;
65
66void benchmark_timer_initialize( void )
67{
68  uint8_t                temp8;
69  uint16_t               temp16;
70  rtems_interrupt_level  level;
71  rtems_isr             *ignored;
72
73  Timer_MHZ = bsp_clicks_per_second / 1000000 ;
74
75  /*
76   *  Timer has never overflowed.  This may not be necessary on some
77   *  implemenations of timer but ....
78   */
79
80  Timer_interrupts /* .i */ = 0;
81  rtems_interrupt_disable( level );
82
83  /*
84   *  Somehow start the timer
85   */
86  /* stop Timer 1  */
87  temp8 = read8(MTU_TSTR) & MTU1_STARTMASK;
88  write8( temp8, MTU_TSTR );
89
90  /* initialize counter 1 */
91  write16( 0, MTU_TCNT1);
92
93  /* Timer 1 is independent of other timers */
94  temp8 = read8(MTU_TSYR) & MTU1_SYNCMASK;
95  write8( temp8, MTU_TSYR );
96
97  /* Timer 1, normal mode */
98  temp8 = read8(MTU_TMDR1) & MTU1_MODEMASK;
99  write8( temp8, MTU_TMDR1 );
100
101  /* x0000000
102   * |||||+++--- Internal Clock
103   * |||++------ Count on rising edge
104   * |++-------- disable TCNT clear
105   * +---------- don`t care
106   */
107  write8( MTU1_TCRMASK, MTU_TCR1 );
108
109  /* gra and grb are not used */
110  write8( MTU1_TIORMASK, MTU_TIOR1 );
111
112  /* reset all status flags */
113  temp8 = read8(MTU_TSR1) & MTU1_STAT_MASK;
114  write8( temp8, MTU_TSR1 );
115
116  /* enable overflow interrupt */
117  write8( MTU1_TIERMASK, MTU_TIER1 );
118
119  /* set interrupt priority */
120  temp16 = read16(INTC_IPRC) & IPRC_MTU1_MASK;
121  temp16 |= MTU1_PRIO;
122  write16( temp16, INTC_IPRC);
123
124  /* initialize ISR */
125  _CPU_ISR_install_raw_handler( MTU1_VECTOR, timerisr, &ignored );
126  rtems_interrupt_enable( level );
127
128  /* start timer 1 */
129  temp8 = read8(MTU_TSTR) | ~MTU1_STARTMASK;
130  write8( temp8, MTU_TSTR );
131}
132
133/*
134 *  The following controls the behavior of benchmark_timer_read().
135 *
136 *  AVG_OVERHEAD is the overhead for starting and stopping the timer.  It
137 *  is usually deducted from the number returned.
138 *
139 *  LEAST_VALID is the lowest number this routine should trust.  Numbers
140 *  below this are "noise" and zero is returned.
141 */
142
143#define AVG_OVERHEAD      1  /* It typically takes X.X microseconds */
144                             /* (Y countdowns) to start/stop the timer. */
145                             /* This value is in microseconds. */
146#define LEAST_VALID       0 /* 20 */ /* Don't trust a clicks value lower than this */
147
148int benchmark_timer_read( void )
149{
150  uint32_t   clicks;
151  uint32_t   total ;
152  /*
153   *  Read the timer and see how many clicks it has been since we started.
154   */
155
156
157  clicks = read16( MTU_TCNT1 );   /* XXX: read some HW here */
158
159  /*
160   *  Total is calculated by taking into account the number of timer overflow
161   *  interrupts since the timer was initialized and clicks since the last
162   *  interrupts.
163   */
164
165  total = clicks + Timer_interrupts * 65536;
166
167  if ( benchmark_timer_find_average_overhead )
168    return total / SCALE;          /* in XXX microsecond units */
169  else
170  {
171    if ( total < LEAST_VALID )
172      return 0;            /* below timer resolution */
173  /*
174   *  Somehow convert total into microseconds
175   */
176    return (total / SCALE - AVG_OVERHEAD) ;
177  }
178}
179
180void benchmark_timer_disable_subtracting_average_overhead(bool find_flag)
181{
182  benchmark_timer_find_average_overhead = find_flag;
183}
184
185/* Timer 1 is used */
186
187#pragma interrupt
188void timerisr( void )
189{
190  uint8_t   temp8;
191
192  /* reset the flags of the status register */
193  temp8 = read8(MTU_TSR1) & MTU1_STAT_MASK;
194  write8( temp8, MTU_TSR1 );
195
196  Timer_interrupts += 1;
197}
Note: See TracBrowser for help on using the repository browser.