Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:01

0001 /**
0002  *  @file
0003  *  @brief Timer for the Hitachi SH 704X
0004  */
0005 
0006 /*
0007  *  Authors: Ralf Corsepius (corsepiu@faw.uni-ulm.de) and
0008  *           Bernd Becker (becker@faw.uni-ulm.de)
0009  *
0010  *  COPYRIGHT (c) 1997-1998, FAW Ulm, Germany
0011  *
0012  *  This program is distributed in the hope that it will be useful,
0013  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
0014  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
0015  *
0016  *  COPYRIGHT (c) 1998.
0017  *  On-Line Applications Research Corporation (OAR).
0018  *
0019  *  The license and distribution terms for this file may be
0020  *  found in the file LICENSE in this distribution or at
0021  *  http://www.rtems.org/license/LICENSE.
0022  */
0023 
0024 #include <rtems.h>
0025 #include <rtems/btimer.h>
0026 
0027 #include <rtems/score/sh_io.h>
0028 #include <rtems/score/iosh7045.h>
0029 
0030 extern uint32_t bsp_clicks_per_second;
0031 
0032 /*
0033  *  We use a Phi/4 timer
0034  */
0035 #define SCALE (Timer_MHZ/4)
0036 
0037 #define MTU1_STARTMASK  0xfd
0038 #define MTU1_SYNCMASK   0xfd
0039 #define MTU1_MODEMASK   0xc0
0040 #define MTU1_TCRMASK    0x01
0041 #define MTU1_TIORMASK   0x88
0042 #define MTU1_STAT_MASK  0xf8
0043 #define MTU1_TIERMASK   0xfc
0044 #define IPRC_MTU1_MASK  0xfff0
0045 
0046 #ifndef MTU1_PRIO
0047 #define MTU1_PRIO 15
0048 #endif
0049 
0050 #define MTU1_VECTOR 86
0051 
0052 extern rtems_isr timerisr(void);
0053 
0054 static uint32_t   Timer_interrupts;
0055 
0056 bool benchmark_timer_find_average_overhead;
0057 
0058 static uint32_t   Timer_MHZ ;
0059 
0060 void benchmark_timer_initialize( void )
0061 {
0062   uint8_t                temp8;
0063   uint16_t               temp16;
0064   rtems_interrupt_level  level;
0065   rtems_isr         *ignored;
0066 
0067   Timer_MHZ = bsp_clicks_per_second / 1000000 ;
0068 
0069   /*
0070    *  Timer has never overflowed.  This may not be necessary on some
0071    *  implemenations of timer but ....
0072    */
0073 
0074   Timer_interrupts /* .i */ = 0;
0075   rtems_interrupt_disable( level );
0076 
0077   /*
0078    *  Somehow start the timer
0079    */
0080   /* stop Timer 1  */
0081   temp8 = read8(MTU_TSTR) & MTU1_STARTMASK;
0082   write8( temp8, MTU_TSTR );
0083 
0084   /* initialize counter 1 */
0085   write16( 0, MTU_TCNT1);
0086 
0087   /* Timer 1 is independent of other timers */
0088   temp8 = read8(MTU_TSYR) & MTU1_SYNCMASK;
0089   write8( temp8, MTU_TSYR );
0090 
0091   /* Timer 1, normal mode */
0092   temp8 = read8(MTU_TMDR1) & MTU1_MODEMASK;
0093   write8( temp8, MTU_TMDR1 );
0094 
0095   /* x0000000
0096    * |||||+++--- Internal Clock
0097    * |||++------ Count on rising edge
0098    * |++-------- disable TCNT clear
0099    * +---------- don`t care
0100    */
0101   write8( MTU1_TCRMASK, MTU_TCR1 );
0102 
0103   /* gra and grb are not used */
0104   write8( MTU1_TIORMASK, MTU_TIOR1 );
0105 
0106   /* reset all status flags */
0107   temp8 = read8(MTU_TSR1) & MTU1_STAT_MASK;
0108   write8( temp8, MTU_TSR1 );
0109 
0110   /* enable overflow interrupt */
0111   write8( MTU1_TIERMASK, MTU_TIER1 );
0112 
0113   /* set interrupt priority */
0114   temp16 = read16(INTC_IPRC) & IPRC_MTU1_MASK;
0115   temp16 |= MTU1_PRIO;
0116   write16( temp16, INTC_IPRC);
0117 
0118   /* initialize ISR */
0119   _CPU_ISR_install_raw_handler( MTU1_VECTOR, timerisr, &ignored );
0120   rtems_interrupt_enable( level );
0121 
0122   /* start timer 1 */
0123   temp8 = read8(MTU_TSTR) | ~MTU1_STARTMASK;
0124   write8( temp8, MTU_TSTR );
0125 }
0126 
0127 /*
0128  *  The following controls the behavior of benchmark_timer_read().
0129  *
0130  *  AVG_OVERHEAD is the overhead for starting and stopping the timer.  It
0131  *  is usually deducted from the number returned.
0132  *
0133  *  LEAST_VALID is the lowest number this routine should trust.  Numbers
0134  *  below this are "noise" and zero is returned.
0135  */
0136 
0137 #define AVG_OVERHEAD      1  /* It typically takes X.X microseconds */
0138                              /* (Y countdowns) to start/stop the timer. */
0139                              /* This value is in microseconds. */
0140 #define LEAST_VALID       0 /* 20 */ /* Don't trust a clicks value lower than this */
0141 
0142 benchmark_timer_t benchmark_timer_read( void )
0143 {
0144   uint32_t   clicks;
0145   uint32_t   total ;
0146   /*
0147    *  Read the timer and see how many clicks it has been since we started.
0148    */
0149 
0150 
0151   clicks = read16( MTU_TCNT1 );   /* XXX: read some HW here */
0152 
0153   /*
0154    *  Total is calculated by taking into account the number of timer overflow
0155    *  interrupts since the timer was initialized and clicks since the last
0156    *  interrupts.
0157    */
0158 
0159   total = clicks + Timer_interrupts * 65536;
0160 
0161   if ( benchmark_timer_find_average_overhead )
0162     return total / SCALE;          /* in XXX microsecond units */
0163   else
0164   {
0165     if ( total < LEAST_VALID )
0166       return 0;            /* below timer resolution */
0167   /*
0168    *  Somehow convert total into microseconds
0169    */
0170     return (total / SCALE - AVG_OVERHEAD) ;
0171   }
0172 }
0173 
0174 void benchmark_timer_disable_subtracting_average_overhead(bool find_flag)
0175 {
0176   benchmark_timer_find_average_overhead = find_flag;
0177 }
0178 
0179 /* Timer 1 is used */
0180 
0181 #pragma interrupt
0182 void timerisr( void )
0183 {
0184   uint8_t   temp8;
0185 
0186   /* reset the flags of the status register */
0187   temp8 = read8(MTU_TSR1) & MTU1_STAT_MASK;
0188   write8( temp8, MTU_TSR1 );
0189 
0190   Timer_interrupts += 1;
0191 }