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

4.11
Last change on this file since ce5c3b3 was ce5c3b3, checked in by Joel Sherrill <joel.sherrill@…>, on Oct 20, 2014 at 6:58:12 PM

nios2/nios2_iss: Fix warnings

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