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

4.115
Last change on this file since df40cc9 was c499856, checked in by Chris Johns <chrisj@…>, on 03/20/14 at 21:10:47

Change all references of rtems.com to rtems.org.

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