source: rtems/c/src/lib/libbsp/m68k/gen68360/clock/ckinit.c @ e8918ec

4.104.114.84.95
Last change on this file since e8918ec was e8918ec, checked in by Joel Sherrill <joel.sherrill@…>, on 12/13/99 at 22:12:03

Patch from Eric Norum <eric@…> to change to gen68360 clock handling.

I got tired of having strange clock rates (e.g. #define
CONFIGURE_MICROSECONDS_PER_TICK 52489) and drifting times-of-day with
the gen68360 BSP so I changed the way the programmable-interval clock
interrupt works. The new version will have some jitter in the intervals
between individual calls to the rtems_clock_tick routine, but the
long-term average will match the CONFIGURE_MICROSECONDS_PER_TICK

  • Property mode set to 100644
File size: 4.6 KB
Line 
1/*
2 * This routine initializes the MC68360 Periodic Interval Timer
3 *
4 * The PIT has rather poor resolution, but it is easy to set up
5 * and requires no housekeeping once it is going.
6 *
7 * Based on the `gen68302' board support package, and covered by the
8 * original distribution terms.
9 *
10 * W. Eric Norum
11 * Saskatchewan Accelerator Laboratory
12 * University of Saskatchewan
13 * Saskatoon, Saskatchewan, CANADA
14 * eric@skatter.usask.ca
15 *
16 *  $Id$
17 */
18
19/*
20 * Input parameters:    NONE
21 *
22 * Output parameters:   NONE
23 *
24 * COPYRIGHT (c) 1989-1999.
25 * On-Line Applications Research Corporation (OAR).
26 *
27 * The license and distribution terms for this file may be
28 * found in the file LICENSE in this distribution or at
29 * http://www.OARcorp.com/rtems/license.html.
30 */
31
32#include <stdlib.h>                     /* for atexit() */
33#include <bsp.h>
34#include <rtems/libio.h>
35#include "m68360.h"
36
37#define CLOCK_VECTOR    120
38#define CLOCK_IRQ_LEVEL 6
39
40/*
41 * Clock_driver_ticks is a monotonically increasing counter of the
42 * number of clock ticks since the driver was initialized.
43 */
44volatile rtems_unsigned32 Clock_driver_ticks;
45
46/*
47 * These are set by clock driver during its init
48 */
49 
50rtems_device_major_number rtems_clock_major = ~0;
51rtems_device_minor_number rtems_clock_minor;
52
53char M360DefaultWatchdogFeeder = 1;
54
55/*
56 * RTEMS and hardware have different notions of clock rate.
57 */
58static unsigned long rtems_nsec_per_tick;
59static unsigned long pit_nsec_per_tick;
60
61/*
62 * Periodic interval timer interrupt handler
63 */
64
65rtems_isr
66Clock_isr (rtems_vector_number vector)
67{
68        static unsigned long nsec;
69
70        /*
71         * See if it's really time for a `tick'
72         */
73        nsec += pit_nsec_per_tick;
74        if (nsec >= rtems_nsec_per_tick) {
75                nsec -= rtems_nsec_per_tick;
76       
77                /*
78                 * Perform a dummy read of DPRAM.
79                 * This works around a bug in Rev. B of the 68360
80                 */
81                m360.dpram0[0];
82
83                /*
84                 * Feed the watchdog
85                 * Application code can override this by
86                 * setting M360DefaultWatchdogFeeder to zero.
87                 */
88                if (M360DefaultWatchdogFeeder) {
89                        m360.swsr = 0x55;
90                        m360.swsr = 0xAA;
91                }
92
93                /*
94                 * Announce the clock tick
95                 */
96                Clock_driver_ticks++;
97                rtems_clock_tick();
98        }
99}
100
101void
102Clock_exit (void)
103{
104        if (BSP_Configuration.ticks_per_timeslice ) {
105                /*
106                 * Turn off periodic interval timer
107                 */
108                m360.pitr &= ~0xFF;
109        }
110}
111
112static void
113Install_clock (rtems_isr_entry clock_isr)
114{
115        Clock_driver_ticks = 0;
116        if ( BSP_Configuration.ticks_per_timeslice ) {
117                /*
118                 * Choose periodic interval timer register value
119                 * The rate at which the periodic interval timer
120                 * can generate interrupts is almost certainly not
121                 * the same as desired by the BSP configuration.
122                 * Handle the difference by choosing the largest PIT
123                 * interval which is less than or equal to the RTEMS
124                 * interval and skipping some hardware interrupts.
125                 * To reduce the jitter in the calls to RTEMS the
126                 * hardware interrupt interval is never less than
127                 * the maximum non-prescaled value from the PIT.
128                 *
129                 * For a 25 MHz external clock the basic clock rate is
130                 *      40 nsec * 128 * 4 = 20.48 usec/tick
131                 */
132                int divisor;
133                extern int m360_clock_rate; /* This should be somewhere in a config file */
134                unsigned long nsec_per_chip_tick = 1000000000 / m360_clock_rate;
135                unsigned long nsec_per_pit_tick = 512 * nsec_per_chip_tick;
136
137                rtems_nsec_per_tick = BSP_Configuration.microseconds_per_tick * 1000;
138                divisor = rtems_nsec_per_tick / nsec_per_pit_tick;
139                if (divisor >= 256) {
140                        divisor = 255;
141                }
142                else if (divisor == 0) {
143                        divisor = 1;
144                }
145                pit_nsec_per_tick = nsec_per_pit_tick * divisor;
146                m360.pitr &= ~0x1FF;
147                m360.picr = (CLOCK_IRQ_LEVEL << 8) | CLOCK_VECTOR;
148                set_vector (clock_isr, CLOCK_VECTOR, 1);
149                m360.pitr |= divisor;
150                atexit (Clock_exit);
151        }
152}
153
154rtems_device_driver
155Clock_initialize(
156        rtems_device_major_number major,
157        rtems_device_minor_number minor,
158        void *pargp
159)
160{
161        Install_clock (Clock_isr);
162 
163        /*
164         * make major/minor avail to others such as shared memory driver
165         */
166        rtems_clock_major = major;
167        rtems_clock_minor = minor;
168 
169        return RTEMS_SUCCESSFUL;
170}
171 
172rtems_device_driver Clock_control(
173        rtems_device_major_number major,
174        rtems_device_minor_number minor,
175        void *pargp
176)
177{
178        rtems_unsigned32 isrlevel;
179        rtems_libio_ioctl_args_t *args = pargp;
180
181        if (args) {
182                /*
183                 * This is hokey, but until we get a defined interface
184                 * to do this, it will just be this simple...
185                 */
186                if (args->command == rtems_build_name('I', 'S', 'R', ' ')) {
187                        Clock_isr( CLOCK_VECTOR);
188                }
189                else if (args->command == rtems_build_name('N', 'E', 'W', ' ')) {
190                        rtems_interrupt_disable( isrlevel );
191                         (void) set_vector( args->buffer, CLOCK_VECTOR, 1 );
192                        rtems_interrupt_enable( isrlevel );
193                }
194        }
195        return RTEMS_SUCCESSFUL;
196}
Note: See TracBrowser for help on using the repository browser.