source: rtems/c/src/lib/libbsp/nios2/nios2_iss/timer/timer.c @ 359e537

4.104.115
Last change on this file since 359e537 was 359e537, checked in by Ralf Corsepius <ralf.corsepius@…>, on Nov 30, 2009 at 5:09:41 AM

Whitespace removal.

  • Property mode set to 100644
File size: 4.0 KB
Line 
1/*  timer.c
2 *
3 *  This file manages the benchmark timer used by the RTEMS Timing Test
4 *  Suite.  Each measured time period is demarcated by calls to
5 *  benchmark_timer_initialize() and benchmark_timer_read().  benchmark_timer_read() usually returns
6 *  the number of microseconds since benchmark_timer_initialize() exitted.
7 *
8 *  NOTE: It is important that the timer start/stop overhead be
9 *        determined when porting or modifying this code.
10 *
11 *  COPYRIGHT (c) 2005-2006 Kolja Waschk rtemsdev/ixo.de
12 *  Derived from no_cpu/no_bsp/timer/timer.c 1.9,
13 *  COPYRIGHT (c) 1989-1999.
14 *  On-Line Applications Research Corporation (OAR).
15 *
16 *  The license and distribution terms for this file may be
17 *  found in the file LICENSE in this distribution or at
18 *  http://www.rtems.com/license/LICENSE.
19 *
20 *  $Id$
21 */
22
23#define TIMER_WRAPS_AFTER_1MS 0
24
25#include <rtems.h>
26#include <rtems/score/cpu.h>
27#include <bsp.h>
28
29volatile uint32_t Timer_interrupts;
30bool benchmark_timer_find_average_overhead;
31
32#define TIMER_REGS ((altera_avalon_timer_regs*)NIOS2_IO_BASE(TIMER_BASE))
33
34void timerisr( void )
35{
36  TIMER_REGS->status = 0;
37  Timer_interrupts++;
38}
39
40void benchmark_timer_initialize( void )
41{
42  uint32_t old_ie;
43
44  /* Disable timer interrupt, stop timer */
45
46  TIMER_REGS->control = ALTERA_AVALON_TIMER_CONTROL_STOP_MSK;
47
48  set_vector((nios2_isr_entry *)timerisr, TIMER_VECTOR, 1);
49
50  /* Enable interrupt processing */
51
52  NIOS2_IENABLE(1 << TIMER_VECTOR);
53
54#if TIMER_WRAPS_AFTER_1MS
55  /* Writing to periodl/h resets the counter and eventually
56     stops it. If the timer hasn't been configured with fixed
57     period, set it to 1 ms now */
58
59  TIMER_REGS->period_hi = (TIMER_FREQ/1000)>>16;
60  TIMER_REGS->period_lo = (TIMER_FREQ/1000)&0xFFFF;
61#else
62  /* Writing to periodl/h resets the counter and eventually
63     stops it. Set max period */
64
65  TIMER_REGS->period_hi = 0xFFFF;
66  TIMER_REGS->period_lo = 0xFFFF;
67#endif
68
69  /* For timers that can be stopped, writing to periodl/h
70     also stopped the timer and we have to manually start it. */
71
72  TIMER_REGS->control = ALTERA_AVALON_TIMER_CONTROL_ITO_MSK |
73                        ALTERA_AVALON_TIMER_CONTROL_CONT_MSK |
74                        ALTERA_AVALON_TIMER_CONTROL_START_MSK;
75
76  /* This is the most safe place for resetting the overflow
77     counter - just _after_ we reset the timer. Depending
78     on the SOPC configuration, the counter may not be
79     stoppable and it doesn't make sense to assume that
80     there is any "safe" period before resetting. */
81
82  Timer_interrupts = 0;
83}
84
85/*
86 *  The following controls the behavior of benchmark_timer_read().
87 *
88 *  AVG_OVEREHAD is the overhead for starting and stopping the timer.  It
89 *  is usually deducted from the number returned.
90 *
91 *  LEAST_VALID is the lowest number this routine should trust.  Numbers
92 *  below this are "noise" and zero is returned.
93 */
94
95#define AVG_OVERHEAD      2      /* It typically takes 2 microseconds */
96                                 /* to start/stop the timer. */
97
98#define LEAST_VALID AVG_OVERHEAD /* Don't trust a value lower than this */
99
100int benchmark_timer_read( void )
101{
102  uint32_t timer_wraps;
103  uint32_t timer_snap;
104  uint32_t timer_ticks;
105  uint32_t total;
106  uint32_t old_ie;
107
108  /* Hold timer */
109  TIMER_REGS->control = ALTERA_AVALON_TIMER_CONTROL_STOP_MSK;
110
111  /* Write to request snapshot of timer value */
112  TIMER_REGS->snap_lo = 0;
113  /* Get snapshot */
114  timer_snap = ((TIMER_REGS->snap_hi)<<16) | TIMER_REGS->snap_lo;
115  timer_wraps = Timer_interrupts;
116
117  /* Restart timer */
118  TIMER_REGS->control = ALTERA_AVALON_TIMER_CONTROL_START_MSK;
119
120#if TIMER_WRAPS_AFTER_1MS
121  timer_ticks = (TIMER_FREQ / 1000) - 1 - timer_snap;
122  total = timer_wraps * 1000;
123#else
124  timer_ticks = 0xFFFFFFFF - timer_snap;
125  total = timer_wraps * 0x80000000 / (TIMER_FREQ / 2000000L);
126#endif
127  total += timer_ticks / (TIMER_FREQ / 1000000L);
128
129  if(total < LEAST_VALID) return 0;
130
131  if(benchmark_timer_find_average_overhead != TRUE) total-= AVG_OVERHEAD;
132
133  return total;
134}
135
136void benchmark_timer_disable_subtracting_average_overhead(bool find_flag)
137{
138  benchmark_timer_find_average_overhead = find_flag;
139}
Note: See TracBrowser for help on using the repository browser.