Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:51

0001 /*
0002  * This file manages the benchmark timer used by the RTEMS Timing Test
0003  * Suite.  Each measured time period is demarcated by calls to
0004  * benchmark_timer_initialize() and benchmark_timer_read(). 
0005  * benchmark_timer_read() usually returns the number of microseconds
0006  * since benchmark_timer_initialize() exitted.
0007  *
0008  *  NOTE: It is important that the timer start/stop overhead be
0009  *        determined when porting or modifying this code.
0010  */
0011 
0012 /*
0013  *  COPYRIGHT (c) 2005-2006 Kolja Waschk rtemsdev/ixo.de
0014  *  Derived from no_cpu/no_bsp/timer/timer.c 1.9,
0015  *  COPYRIGHT (c) 1989-1999.
0016  *  On-Line Applications Research Corporation (OAR).
0017  *
0018  *  The license and distribution terms for this file may be
0019  *  found in the file LICENSE in this distribution or at
0020  *  http://www.rtems.org/license/LICENSE.
0021  */
0022 
0023 #define TIMER_WRAPS_AFTER_1MS 0
0024 
0025 #include <rtems.h>
0026 #include <rtems/btimer.h>
0027 #include <rtems/score/cpu.h>
0028 #include <bsp.h>
0029 
0030 volatile uint32_t Timer_interrupts;
0031 bool benchmark_timer_find_average_overhead;
0032 
0033 #define TIMER_REGS ((altera_avalon_timer_regs*)NIOS2_IO_BASE(TIMER_BASE))
0034 
0035 static rtems_isr timerisr(rtems_vector_number vector)
0036 {
0037   TIMER_REGS->status = 0;
0038   Timer_interrupts++;
0039 }
0040 
0041 void benchmark_timer_initialize( void )
0042 {
0043   /* Disable timer interrupt, stop timer */
0044 
0045   TIMER_REGS->control = ALTERA_AVALON_TIMER_CONTROL_STOP_MSK;
0046 
0047   set_vector(timerisr, TIMER_VECTOR, 1);
0048 
0049   /* Enable interrupt processing */
0050 
0051   NIOS2_IENABLE(1 << TIMER_VECTOR);
0052 
0053 #if TIMER_WRAPS_AFTER_1MS
0054   /* Writing to periodl/h resets the counter and eventually
0055      stops it. If the timer hasn't been configured with fixed
0056      period, set it to 1 ms now */
0057 
0058   TIMER_REGS->period_hi = (TIMER_FREQ/1000)>>16;
0059   TIMER_REGS->period_lo = (TIMER_FREQ/1000)&0xFFFF;
0060 #else
0061   /* Writing to periodl/h resets the counter and eventually
0062      stops it. Set max period */
0063 
0064   TIMER_REGS->period_hi = 0xFFFF;
0065   TIMER_REGS->period_lo = 0xFFFF;
0066 #endif
0067 
0068   /* For timers that can be stopped, writing to periodl/h
0069      also stopped the timer and we have to manually start it. */
0070 
0071   TIMER_REGS->control = ALTERA_AVALON_TIMER_CONTROL_ITO_MSK |
0072                         ALTERA_AVALON_TIMER_CONTROL_CONT_MSK |
0073                         ALTERA_AVALON_TIMER_CONTROL_START_MSK;
0074 
0075   /* This is the most safe place for resetting the overflow
0076      counter - just _after_ we reset the timer. Depending
0077      on the SOPC configuration, the counter may not be
0078      stoppable and it doesn't make sense to assume that
0079      there is any "safe" period before resetting. */
0080 
0081   Timer_interrupts = 0;
0082 }
0083 
0084 /*
0085  *  The following controls the behavior of benchmark_timer_read().
0086  *
0087  *  AVG_OVEREHAD is the overhead for starting and stopping the timer.  It
0088  *  is usually deducted from the number returned.
0089  *
0090  *  LEAST_VALID is the lowest number this routine should trust.  Numbers
0091  *  below this are "noise" and zero is returned.
0092  */
0093 
0094 #define AVG_OVERHEAD      2      /* It typically takes 2 microseconds */
0095                                  /* to start/stop the timer. */
0096 
0097 #define LEAST_VALID AVG_OVERHEAD /* Don't trust a value lower than this */
0098 
0099 benchmark_timer_t benchmark_timer_read( void )
0100 {
0101   uint32_t timer_wraps;
0102   uint32_t timer_snap;
0103   uint32_t timer_ticks;
0104   uint32_t total;
0105 
0106   /* Hold timer */
0107   TIMER_REGS->control = ALTERA_AVALON_TIMER_CONTROL_STOP_MSK;
0108 
0109   /* Write to request snapshot of timer value */
0110   TIMER_REGS->snap_lo = 0;
0111   /* Get snapshot */
0112   timer_snap = ((TIMER_REGS->snap_hi)<<16) | TIMER_REGS->snap_lo;
0113   timer_wraps = Timer_interrupts;
0114 
0115   /* Restart timer */
0116   TIMER_REGS->control = ALTERA_AVALON_TIMER_CONTROL_START_MSK;
0117 
0118 #if TIMER_WRAPS_AFTER_1MS
0119   timer_ticks = (TIMER_FREQ / 1000) - 1 - timer_snap;
0120   total = timer_wraps * 1000;
0121 #else
0122   timer_ticks = 0xFFFFFFFF - timer_snap;
0123   total = timer_wraps * 0x80000000 / (TIMER_FREQ / 2000000L);
0124 #endif
0125   total += timer_ticks / (TIMER_FREQ / 1000000L);
0126 
0127   if(total < LEAST_VALID) return 0;
0128 
0129   if(benchmark_timer_find_average_overhead != TRUE) total-= AVG_OVERHEAD;
0130 
0131   return total;
0132 }
0133 
0134 void benchmark_timer_disable_subtracting_average_overhead(bool find_flag)
0135 {
0136   benchmark_timer_find_average_overhead = find_flag;
0137 }