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

4.115
Last change on this file since 8fbe2e6 was 8fbe2e6, checked in by Joel Sherrill <joel.sherrill@…>, on 09/04/14 at 13:59:49

Use correct prototype of benchmark_timer_read()

This change starts with removing the effectively empty file
timerdrv.h. The prototypes for benchmark_timer_XXX() were in
btimer.h which was not universally used. Thus every use of
timerdrv.h had to be changed to btimer.h. Then the prototypes
for benchmark_timer_read() had to be adjusted to return
benchmark_timer_t rather than int or uint32_t.

I took this opportunity to also correct the file headers to
separate the copyright from the file description comments which
is needed to ensure the copyright isn't propagated into Doxygen
output.

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