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 703X
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/ispsh7032.h>
0029 #include <rtems/score/iosh7032.h>
0030 
0031 extern uint32_t bsp_clicks_per_second;
0032 
0033 #define I_CLK_PHI_1     0
0034 #define I_CLK_PHI_2     1
0035 #define I_CLK_PHI_4     2
0036 #define I_CLK_PHI_8     3
0037 
0038 /*
0039  * Set I_CLK_PHI to one of the I_CLK_PHI_X values from above to choose
0040  * a PHI/X clock rate.
0041  */
0042 
0043 #define I_CLK_PHI       I_CLK_PHI_4
0044 #define CLOCK_SCALE     (1<<I_CLK_PHI)
0045 
0046 #define ITU1_STARTMASK  0xfd
0047 #define ITU1_SYNCMASK   0xfd
0048 #define ITU1_MODEMASK   0xfd
0049 #define ITU1_TCRMASK    (0x00 | I_CLK_PHI)
0050 #define ITU1_TIORMASK   0x88
0051 #define ITU1_STAT_MASK  0xf8
0052 #define ITU1_TIERMASK   0xfc
0053 #define IPRC_ITU1_MASK  0xfff0
0054 
0055 #ifndef ITU1_PRIO
0056 #define ITU1_PRIO 15
0057 #endif
0058 
0059 #define ITU1_VECTOR OVI1_ISP_V
0060 
0061 extern rtems_isr timerisr(void);
0062 
0063 static uint32_t   Timer_interrupts;
0064 
0065 bool benchmark_timer_find_average_overhead;
0066 
0067 static uint32_t   Timer_HZ ;
0068 
0069 void benchmark_timer_initialize( void )
0070 {
0071   uint8_t                temp8;
0072   uint16_t               temp16;
0073   rtems_interrupt_level  level;
0074   rtems_isr             *ignored;
0075 
0076   Timer_HZ = bsp_clicks_per_second / CLOCK_SCALE ;
0077 
0078   /*
0079    *  Timer has never overflowed.  This may not be necessary on some
0080    *  implemenations of timer but ....
0081    */
0082 
0083   Timer_interrupts /* .i */ = 0;
0084   rtems_interrupt_disable( level );
0085 
0086   /*
0087    *  Somehow start the timer
0088    */
0089   /* stop Timer 1  */
0090   temp8 = read8(ITU_TSTR) & ITU1_STARTMASK;
0091   write8( temp8, ITU_TSTR );
0092 
0093   /* initialize counter 1 */
0094   write16( 0, ITU_TCNT1 );
0095 
0096   /* Timer 1 is independent of other timers */
0097   temp8 = read8(ITU_TSNC) & ITU1_SYNCMASK;
0098   write8( temp8, ITU_TSNC );
0099 
0100   /* Timer 1, normal mode */
0101   temp8 = read8(ITU_TMDR) & ITU1_MODEMASK;
0102   write8( temp8, ITU_TMDR );
0103 
0104   /* Use a Phi/X counter */
0105   write8( ITU1_TCRMASK, ITU_TCR1 );
0106 
0107   /* gra and grb are not used */
0108   write8( ITU1_TIORMASK, ITU_TIOR1 );
0109 
0110   /* reset all status flags */
0111   temp8 = read8(ITU_TSR1) & ITU1_STAT_MASK;
0112   write8( temp8, ITU_TSR1 );
0113 
0114   /* enable overflow interrupt */
0115   write8( ITU1_TIERMASK, ITU_TIER1 );
0116 
0117   /* set interrupt priority */
0118   temp16 = read16(INTC_IPRC) & IPRC_ITU1_MASK;
0119   temp16 |= ITU1_PRIO;
0120   write16( temp16, INTC_IPRC );
0121 
0122   /* initialize ISR */
0123   _CPU_ISR_install_raw_handler( ITU1_VECTOR, timerisr, &ignored );
0124   rtems_interrupt_enable( level );
0125 
0126   /* start timer 1 */
0127   temp8 = read8(ITU_TSTR) | ~ITU1_STARTMASK;
0128   write8( temp8, ITU_TSTR );
0129 }
0130 
0131 /*
0132  *  The following controls the behavior of benchmark_timer_read().
0133  *
0134  *  AVG_OVERHEAD is the overhead for starting and stopping the timer.  It
0135  *  is usually deducted from the number returned.
0136  *
0137  *  LEAST_VALID is the lowest number this routine should trust.  Numbers
0138  *  below this are "noise" and zero is returned.
0139  */
0140 
0141 #define AVG_OVERHEAD      1  /* It typically takes X.X microseconds */
0142                              /* (Y countdowns) to start/stop the timer. */
0143                              /* This value is in microseconds. */
0144 #define LEAST_VALID       0 /* 20 */ /* Don't trust a clicks value lower than this */
0145 
0146 benchmark_timer_t benchmark_timer_read( void )
0147 {
0148   uint32_t   cclicks;
0149   uint32_t   total ;
0150   /*
0151    *  Read the timer and see how many clicks it has been since we started.
0152    */
0153 
0154 
0155   cclicks = read16( ITU_TCNT1 );    /* XXX: read some HW here */
0156 
0157   /*
0158    *  Total is calculated by taking into account the number of timer overflow
0159    *  interrupts since the timer was initialized and clicks since the last
0160    *  interrupts.
0161    */
0162 
0163   total = cclicks + Timer_interrupts * 65536;
0164 
0165   if ( benchmark_timer_find_average_overhead )
0166     return total / CLOCK_SCALE;          /* in XXX microsecond units */
0167   else
0168   {
0169     if ( total < LEAST_VALID )
0170       return 0;            /* below timer resolution */
0171   /*
0172    *  Somehow convert total into microseconds
0173    */
0174     return (total / CLOCK_SCALE - AVG_OVERHEAD);
0175   }
0176 }
0177 
0178 void benchmark_timer_disable_subtracting_average_overhead(bool find_flag)
0179 {
0180   benchmark_timer_find_average_overhead = find_flag;
0181 }
0182 
0183 /* Timer 1 is used */
0184 
0185 #pragma interrupt
0186 void timerisr( void )
0187 {
0188   uint8_t   temp8;
0189 
0190   /* reset the flags of the status register */
0191   temp8 = read8(ITU_TSR1) & ITU1_STAT_MASK;
0192   write8( temp8, ITU_TSR1 );
0193 
0194   Timer_interrupts += 1;
0195 }