source: rtems/c/src/lib/libcpu/sh/sh7032/clock/ckinit.c @ 0dd1d44

4.104.114.84.95
Last change on this file since 0dd1d44 was 0dd1d44, checked in by Joel Sherrill <joel.sherrill@…>, on Jan 11, 2000 at 5:34:20 PM

Removed old hack of using Configuration Table entry ticks_per_timeslice
being set to 0 to indicate that there should be no Clock Tick. This
was used by the Timing Tests to avoid clock tick overhead perturbing
execution times. Now the Timing Tests simply leave the Clock Tick
Driver out of the Device Driver Table.

  • Property mode set to 100644
File size: 8.4 KB
Line 
1/*
2 *  This file contains the clock driver the Hitachi SH 703X
3 *
4 *  Authors: Ralf Corsepius (corsepiu@faw.uni-ulm.de) and
5 *           Bernd Becker (becker@faw.uni-ulm.de)
6 *
7 *  COPYRIGHT (c) 1997-1998, FAW Ulm, Germany
8 *
9 *  This program is distributed in the hope that it will be useful,
10 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 *
13 *
14 *  COPYRIGHT (c) 1998.
15 *  On-Line Applications Research Corporation (OAR).
16 *  Copyright assigned to U.S. Government, 1994.
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.OARcorp.com/rtems/license.html.
21 *
22 *  $Id$
23 */
24
25#include <rtems.h>
26
27#include <stdlib.h>
28
29#include <rtems/libio.h>
30#include <rtems/score/sh_io.h>
31#include <rtems/score/sh.h>
32#include <rtems/score/ispsh7032.h>
33#include <rtems/score/iosh7032.h>
34
35#ifndef CLOCKPRIO
36#define CLOCKPRIO 10
37#endif
38
39#define I_CLK_PHI_1     0
40#define I_CLK_PHI_2     1
41#define I_CLK_PHI_4     2
42#define I_CLK_PHI_8     3
43
44/*
45 * Set I_CLK_PHI to one of the I_CLK_PHI_X values from above to choose
46 * a PHI/X clock rate.
47 */
48 
49#define I_CLK_PHI       I_CLK_PHI_4
50#define CLOCK_SCALE     (1<<I_CLK_PHI)
51
52#define ITU0_STARTMASK  0xfe
53#define ITU0_SYNCMASK   0xfe
54#define ITU0_MODEMASK   0xfe
55#define ITU0_TCRMASK    (0x20 | I_CLK_PHI)
56#define ITU_STAT_MASK   0xf8
57#define ITU0_IRQMASK    0xfe
58#define ITU0_TIERMASK   0x01
59#define IPRC_ITU0_MASK  0xff0f
60#define ITU0_TIORVAL    0x08
61
62/*
63 * clicks_per_tick := clicks_per_sec * usec_per_tick
64 *
65 * This is a very expensive function ;-)
66 *
67 * Below are two variants:
68 * 1. A variant applying integer arithmetics, only.
69 * 2. A variant applying floating point arithmetics
70 *
71 * The floating point variant pulls in the fmath routines when linking,
72 * resulting in slightly larger executables for applications that do not
73 * apply fmath otherwise. However, the imath variant is significantly slower
74 * than the fmath variant and more complex.
75 *
76 * Assuming that most applications will not use fmath, but are critical
77 * in memory size constraints, we apply the integer variant.
78 *
79 * To the sake of simplicity, we might abandon one of both variants in
80 * future.
81 */
82static unsigned int sh_clicks_per_tick( 
83  unsigned int clicks_per_sec,
84  unsigned int usec_per_tick )
85{
86#if 1
87  unsigned int clicks_per_tick = 0 ;
88 
89  unsigned int b = clicks_per_sec ;
90  unsigned int c = 1000000 ;
91  unsigned int d = 1 ;
92  unsigned int a = ( ( b / c ) * usec_per_tick ) / d;
93
94  clicks_per_tick += a ;
95
96  while ( ( b %= c ) > 0 )
97  {
98    c /= 10 ;
99    d *= 10 ;
100    a = ( ( b / c ) * usec_per_tick ) / d ;
101    clicks_per_tick += a ;
102  } 
103  return clicks_per_tick ;
104#else
105  double fclicks_per_tick = 
106    ((double) clicks_per_sec * (double) usec_per_tick) / 1000000.0 ;
107  return (unsigned32) fclicks_per_tick ;
108#endif
109}
110
111/*
112 *  The interrupt vector number associated with the clock tick device
113 *  driver.
114 */
115
116#define CLOCK_VECTOR IMIA0_ISP_V
117
118/*
119 *  Clock_driver_ticks is a monotonically increasing counter of the
120 *  number of clock ticks since the driver was initialized.
121 */
122
123volatile rtems_unsigned32 Clock_driver_ticks;
124
125static void Clock_exit( void );
126static rtems_isr Clock_isr( rtems_vector_number vector );
127
128/*
129 *  Clock_isrs is the number of clock ISRs until the next invocation of
130 *  the RTEMS clock tick routine.  The clock tick device driver
131 *  gets an interrupt once a millisecond and counts down until the
132 *  length of time between the user configured microseconds per tick
133 *  has passed.
134 */
135
136rtems_unsigned32 Clock_isrs;              /* ISRs until next tick */
137static rtems_unsigned32 Clock_isrs_const;        /* only calculated once */
138
139/*
140 * These are set by clock driver during its init
141 */
142 
143rtems_device_major_number rtems_clock_major = ~0;
144rtems_device_minor_number rtems_clock_minor;
145
146/*
147 *  The previous ISR on this clock tick interrupt vector.
148 */
149
150rtems_isr_entry  Old_ticker;
151
152/*
153 *  Isr Handler
154 */
155
156rtems_isr Clock_isr(
157  rtems_vector_number vector
158)
159{
160  /*
161   * bump the number of clock driver ticks since initialization
162   *
163   * determine if it is time to announce the passing of tick as configured
164   * to RTEMS through the rtems_clock_tick directive
165   *
166   * perform any timer dependent tasks
167   */
168  unsigned8 temp;
169
170  /* reset the flags of the status register */
171  temp = read8( ITU_TSR0) & ITU_STAT_MASK;
172  write8( temp, ITU_TSR0);
173
174  Clock_driver_ticks++ ;
175
176  if( Clock_isrs == 1)
177    {
178      rtems_clock_tick();
179      Clock_isrs = Clock_isrs_const;
180    }
181  else
182    {
183      Clock_isrs-- ;
184    }
185}
186
187/*
188 *  Install_clock
189 *
190 *  Install a clock tick handler and reprograms the chip.  This
191 *  is used to initially establish the clock tick.
192 */
193
194void Install_clock(
195  rtems_isr_entry clock_isr
196)
197{
198  unsigned8 temp8 = 0;
199  unsigned32 microseconds_per_tick ;
200  unsigned32 cclicks_per_tick ;
201  unsigned16 Clock_limit ;
202 
203  /*
204   *  Initialize the clock tick device driver variables
205   */
206
207  Clock_driver_ticks = 0;
208   
209  if ( rtems_configuration_get_microseconds_per_tick() != 0 )
210    microseconds_per_tick = rtems_configuration_get_microseconds_per_tick() ;
211  else
212    microseconds_per_tick = 10000 ; /* 10000 us */
213
214  /* clock clicks per tick */
215  cclicks_per_tick = 
216    sh_clicks_per_tick(
217      rtems_cpu_configuration_get_clicks_per_second() / CLOCK_SCALE,
218      microseconds_per_tick );
219
220  Clock_isrs_const = cclicks_per_tick >> 16 ;
221  if ( ( cclicks_per_tick | 0xffff ) > 0 ) 
222    Clock_isrs_const++ ;
223  Clock_limit = cclicks_per_tick / Clock_isrs_const ;
224  Clock_isrs = Clock_isrs_const;
225
226  rtems_interrupt_catch( Clock_isr, CLOCK_VECTOR, &Old_ticker );
227  /*
228   *  Hardware specific initialize goes here
229   */
230 
231  /* stop Timer 0 */
232  temp8 = read8( ITU_TSTR) & ITU0_STARTMASK;
233  write8( temp8, ITU_TSTR);
234
235  /* set initial counter value to 0 */
236  write16( 0, ITU_TCNT0);
237
238  /* Timer 0 runs independent */
239  temp8 = read8( ITU_TSNC) & ITU0_SYNCMASK;
240  write8( temp8, ITU_TSNC);
241
242  /* Timer 0 normal mode */
243  temp8 = read8( ITU_TMDR) & ITU0_MODEMASK;
244  write8( temp8, ITU_TMDR);
245
246  /* TCNT is cleared by GRA ; internal clock /4 */
247  write8( ITU0_TCRMASK , ITU_TCR0);
248
249  /* use GRA without I/O - pins  */
250  write8( ITU0_TIORVAL, ITU_TIOR0); 
251   
252  /* reset flags of the status register */
253  temp8 = read8( ITU_TSR0) & ITU_STAT_MASK;
254  write8( temp8, ITU_TSR0);
255
256  /* Irq if is equal GRA */
257  temp8 = read8( ITU_TIER0) | ITU0_TIERMASK;
258  write8( temp8, ITU_TIER0);
259
260  /* set interrupt priority */
261  if( sh_set_irq_priority( CLOCK_VECTOR, CLOCKPRIO ) != RTEMS_SUCCESSFUL)
262    rtems_fatal_error_occurred( RTEMS_NOT_CONFIGURED);
263
264  /* set counter limits */
265  write16( Clock_limit, ITU_GRA0);
266   
267  /* start counter */
268  temp8 = read8( ITU_TSTR) |~ITU0_STARTMASK;
269  write8( temp8, ITU_TSTR);
270
271  /*
272   *  Schedule the clock cleanup routine to execute if the application exits.
273   */
274
275  atexit( Clock_exit );
276}
277
278/*
279 *  Clean up before the application exits
280 */
281
282void Clock_exit( void )
283{
284  unsigned8 temp8 = 0;
285
286  /* turn off the timer interrupts */
287  /* set interrupt priority to 0 */
288  if( sh_set_irq_priority( CLOCK_VECTOR, 0 ) != RTEMS_SUCCESSFUL)
289    rtems_fatal_error_occurred( RTEMS_UNSATISFIED);
290
291/*
292 *   temp16 = read16( ITU_TIER0) & IPRC_ITU0_IRQMASK;
293 *   write16( temp16, ITU_TIER0);
294 */
295
296  /* stop counter */
297  temp8 = read8( ITU_TSTR) & ITU0_STARTMASK;
298  write8( temp8, ITU_TSTR);
299
300  /* old vector shall not be installed */
301}
302
303/*
304 *  Clock_initialize
305 *
306 *  Device driver entry point for clock tick driver initialization.
307 */
308
309rtems_device_driver Clock_initialize(
310  rtems_device_major_number major,
311  rtems_device_minor_number minor,
312  void *pargp
313)
314{
315  Install_clock( Clock_isr );
316 
317  /*
318   * make major/minor avail to others such as shared memory driver
319   */
320 
321  rtems_clock_major = major;
322  rtems_clock_minor = minor;
323 
324  return RTEMS_SUCCESSFUL;
325}
326
327rtems_device_driver Clock_control(
328  rtems_device_major_number major,
329  rtems_device_minor_number minor,
330  void *pargp
331)
332{
333  rtems_unsigned32 isrlevel;
334  rtems_libio_ioctl_args_t *args = pargp;
335 
336  if (args != 0)
337    {
338      /*
339       * This is hokey, but until we get a defined interface
340       * to do this, it will just be this simple...
341       */
342     
343      if (args->command == rtems_build_name('I', 'S', 'R', ' '))
344        {
345          Clock_isr(CLOCK_VECTOR);
346        }
347      else if (args->command == rtems_build_name('N', 'E', 'W', ' '))
348        {
349          rtems_isr_entry       ignored ;
350          rtems_interrupt_disable( isrlevel );
351          rtems_interrupt_catch( args->buffer, CLOCK_VECTOR, &ignored );
352         
353          rtems_interrupt_enable( isrlevel );
354        }
355    }
356  return RTEMS_SUCCESSFUL;
357}
Note: See TracBrowser for help on using the repository browser.