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

4.104.114.84.95
Last change on this file since f52111f was 35ece2e, checked in by Joel Sherrill <joel.sherrill@…>, on 02/11/00 at 15:21:40

Patch from Eric Norum <eric@…> based on working with
Bob Wisdon <bobwis@…> and Chris Johns <ccj@…>
to resolve a random network lockup problem.

ckinit.c:

Occasional network lockups have been noted when the PIT has a higher
interrupt request level than the CPM. The SCC1 bit in the CISR is set
even though the SCC1 interrupt handler is not active. This blocks
interrupts from SCC1 (and all other CPM sources) and locks up the
system. It has not been determined whether the error is within the
68360 or in the RTEMS interrupt support assembler code. The solution,
for now, is to set both PIT and CPM interrupt request levels to the same
value (4).

network.c:

Set CPM transmitter buffer pointer (_tbptr) to beginning of frame
before restarting transmitter. Don't retire transmitter buffer
descriptors belonging to the restarted frame.

  • Property mode set to 100644
File size: 4.4 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 4
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        /*
105         * Turn off periodic interval timer
106         */
107        m360.pitr &= ~0xFF;
108}
109
110static void
111Install_clock (rtems_isr_entry clock_isr)
112{
113        int divisor;
114        extern int m360_clock_rate; /* This should be somewhere in a config file */
115        unsigned long nsec_per_chip_tick = 1000000000 / m360_clock_rate;
116        unsigned long nsec_per_pit_tick = 512 * nsec_per_chip_tick;
117
118        Clock_driver_ticks = 0;
119        /*
120         * Choose periodic interval timer register value
121         * The rate at which the periodic interval timer
122         * can generate interrupts is almost certainly not
123         * the same as desired by the BSP configuration.
124         * Handle the difference by choosing the largest PIT
125         * interval which is less than or equal to the RTEMS
126         * interval and skipping some hardware interrupts.
127         * To reduce the jitter in the calls to RTEMS the
128         * hardware interrupt interval is never less than
129         * the maximum non-prescaled value from the PIT.
130         *
131         * For a 25 MHz external clock the basic clock rate is
132         *      40 nsec * 128 * 4 = 20.48 usec/tick
133         */
134
135        rtems_nsec_per_tick = BSP_Configuration.microseconds_per_tick * 1000;
136        divisor = rtems_nsec_per_tick / nsec_per_pit_tick;
137        if (divisor >= 256) {
138                divisor = 255;
139        } else if (divisor == 0) {
140                divisor = 1;
141        }
142        pit_nsec_per_tick = nsec_per_pit_tick * divisor;
143        m360.pitr &= ~0x1FF;
144        m360.picr = (CLOCK_IRQ_LEVEL << 8) | CLOCK_VECTOR;
145        set_vector (clock_isr, CLOCK_VECTOR, 1);
146        m360.pitr |= divisor;
147        atexit (Clock_exit);
148}
149
150rtems_device_driver
151Clock_initialize(
152        rtems_device_major_number major,
153        rtems_device_minor_number minor,
154        void *pargp
155)
156{
157        Install_clock (Clock_isr);
158 
159        /*
160         * make major/minor avail to others such as shared memory driver
161         */
162        rtems_clock_major = major;
163        rtems_clock_minor = minor;
164 
165        return RTEMS_SUCCESSFUL;
166}
167 
168rtems_device_driver Clock_control(
169        rtems_device_major_number major,
170        rtems_device_minor_number minor,
171        void *pargp
172)
173{
174        rtems_unsigned32 isrlevel;
175        rtems_libio_ioctl_args_t *args = pargp;
176
177        if (args) {
178                /*
179                 * This is hokey, but until we get a defined interface
180                 * to do this, it will just be this simple...
181                 */
182                if (args->command == rtems_build_name('I', 'S', 'R', ' ')) {
183                        Clock_isr( CLOCK_VECTOR);
184                }
185                else if (args->command == rtems_build_name('N', 'E', 'W', ' ')) {
186                        rtems_interrupt_disable( isrlevel );
187                         (void) set_vector( args->buffer, CLOCK_VECTOR, 1 );
188                        rtems_interrupt_enable( isrlevel );
189                }
190        }
191        return RTEMS_SUCCESSFUL;
192}
Note: See TracBrowser for help on using the repository browser.