OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [kernel/] [v2_0/] [include/] [intr.hxx] - Blame information for rev 631

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
#ifndef CYGONCE_KERNEL_INTR_HXX
2
#define CYGONCE_KERNEL_INTR_HXX
3
 
4
//==========================================================================
5
//
6
//      intr.hxx
7
//
8
//      Interrupt class declaration(s)
9
//
10
//==========================================================================
11
//####ECOSGPLCOPYRIGHTBEGIN####
12
// -------------------------------------------
13
// This file is part of eCos, the Embedded Configurable Operating System.
14
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
15
//
16
// eCos is free software; you can redistribute it and/or modify it under
17
// the terms of the GNU General Public License as published by the Free
18
// Software Foundation; either version 2 or (at your option) any later version.
19
//
20
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
21
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
22
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
23
// for more details.
24
//
25
// You should have received a copy of the GNU General Public License along
26
// with eCos; if not, write to the Free Software Foundation, Inc.,
27
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
28
//
29
// As a special exception, if other files instantiate templates or use macros
30
// or inline functions from this file, or you compile this file and link it
31
// with other works to produce a work based on this file, this file does not
32
// by itself cause the resulting work to be covered by the GNU General Public
33
// License. However the source code for this file must still be made available
34
// in accordance with section (3) of the GNU General Public License.
35
//
36
// This exception does not invalidate any other reasons why a work based on
37
// this file might be covered by the GNU General Public License.
38
//
39
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
40
// at http://sources.redhat.com/ecos/ecos-license/
41
// -------------------------------------------
42
//####ECOSGPLCOPYRIGHTEND####
43
//==========================================================================
44
//#####DESCRIPTIONBEGIN####
45
//
46
// Author(s):   nickg
47
// Contributors:        nickg
48
// Date:        1997-09-09
49
// Purpose:     Define Interrupt class interfaces
50
// Description: The classes defined here provide the APIs for handling
51
//              interrupts.
52
// Usage:       #include "intr.hxx"
53
//
54
//
55
//####DESCRIPTIONEND####
56
//
57
//==========================================================================
58
 
59
#include 
60
 
61
#include 
62
 
63
// -------------------------------------------------------------------------
64
// Default definitions
65
 
66
// Some HALs define the ISR table to be a different size to the number
67
// of ISR vectors. These HALs will define CYGNUM_HAL_ISR_TABLE_SIZE. All
68
// other HALs will have the table size equal to the number of vectors.
69
 
70
#ifndef CYGNUM_HAL_ISR_TABLE_SIZE
71
# define CYGNUM_HAL_ISR_TABLE_SIZE      CYGNUM_HAL_ISR_COUNT
72
#endif
73
 
74
// -------------------------------------------------------------------------
75
// Function prototype typedefs
76
 
77
 
78
// VSR = Vector Service Routine. This is the code attached directly to an
79
// interrupt vector. It is very architecture/platform specific and usually
80
// must be written in assembler.
81
 
82
typedef void  cyg_VSR();
83
 
84
// ISR = Interrupt Service Routine. This is called from the default
85
// VSR in response to an interrupt. It may access shared data but may
86
// not call kernel routines. The return value may be
87
// Cyg_Interrupt::HANDLED and/or Cyg_Interrupt::CALL_DSR.
88
 
89
typedef cyg_uint32 cyg_ISR(cyg_vector vector, CYG_ADDRWORD data);
90
 
91
// DSR = Deferred Service Routine. This is called if the ISR returns
92
// the Cyg_Interrupt::CALL_DSR bit. It is called at a "safe" point in
93
// the kernel where it may make calls on kernel routines. The count
94
// argument indicates how many times the ISR has asked for the DSR to
95
// be posted since the last time the DSR ran.
96
 
97
typedef void cyg_DSR(cyg_vector vector, cyg_ucount32 count, CYG_ADDRWORD data);
98
 
99
// -------------------------------------------------------------------------
100
// Include HAL definitions
101
 
102
class Cyg_Interrupt;
103
 
104
#include 
105
 
106
#include 
107
 
108
#ifndef HAL_INTERRUPT_STACK_CALL_PENDING_DSRS
109
#define HAL_INTERRUPT_STACK_CALL_PENDING_DSRS()    \
110
      Cyg_Interrupt::call_pending_DSRs_inner()
111
#endif
112
 
113
externC void interrupt_end(
114
    cyg_uint32          isr_ret,
115
    Cyg_Interrupt       *intr,
116
    HAL_SavedRegisters  *ctx
117
    );
118
 
119
externC void cyg_interrupt_post_dsr( CYG_ADDRWORD intr_obj );
120
externC void cyg_interrupt_call_pending_DSRs( void );
121
 
122
// -------------------------------------------------------------------------
123
// Interrupt class. This both represents each interrupt and provides a static
124
// interface for controlling the interrupt hardware.
125
 
126
class Cyg_Interrupt
127
{
128
 
129
    friend class Cyg_Scheduler;
130
    friend void interrupt_end( cyg_uint32,
131
                               Cyg_Interrupt *,
132
                               HAL_SavedRegisters *);
133
    friend void cyg_interrupt_post_dsr( CYG_ADDRWORD intr_obj );
134
    friend void cyg_interrupt_call_pending_DSRs( void );
135
 
136
    cyg_vector          vector;         // Interrupt vector
137
 
138
    cyg_priority        priority;       // Queuing priority
139
 
140
    cyg_ISR             *isr;           // Pointer to ISR
141
 
142
    cyg_DSR             *dsr;           // Pointer to DSR
143
 
144
    CYG_ADDRWORD        data;           // Data pointer
145
 
146
 
147
 
148
    // DSR handling interface called by the scheduler
149
 
150
                                        // Check for pending DSRs
151
    static cyg_bool     DSRs_pending();
152
 
153
                                        // Call any pending DSRs
154
    static void         call_pending_DSRs();
155
    static void         call_pending_DSRs_inner();
156
 
157
    // DSR handling interface called by the scheduler and HAL
158
    // interrupt arbiters.
159
 
160
    void                post_dsr();     // Post the DSR for this interrupt
161
 
162
 
163
 
164
    // Data structures for handling DSR calls.  We implement two DSR
165
    // handling mechanisms, a list based one and a table based
166
    // one. The list based mechanism is safe with respect to temporary
167
    // overloads and will not run out of resource. However it requires
168
    // extra data per interrupt object, and interrupts must be turned
169
    // off briefly when delivering the DSR. The table based mechanism
170
    // does not need unnecessary interrupt switching, but may be prone
171
    // to overflow on overload. However, since a correctly programmed
172
    // real time application should not experience such a condition,
173
    // the table based mechanism is more efficient for real use. The
174
    // list based mechainsm is enabled by default since it is safer to
175
    // use during development.
176
 
177
#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_TABLE
178
 
179
    static Cyg_Interrupt *dsr_table[CYGNUM_KERNEL_CPU_MAX]
180
                                   [CYGNUM_KERNEL_INTERRUPTS_DSRS_TABLE_SIZE]
181
                                   CYGBLD_ANNOTATE_VARIABLE_INTR;
182
 
183
    static cyg_ucount32 dsr_table_head[CYGNUM_KERNEL_CPU_MAX]
184
                                      CYGBLD_ANNOTATE_VARIABLE_INTR;
185
 
186
    static volatile cyg_ucount32 dsr_table_tail[CYGNUM_KERNEL_CPU_MAX]
187
                                               CYGBLD_ANNOTATE_VARIABLE_INTR;
188
 
189
#endif
190
#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST
191
 
192
    // Number of DSR posts made
193
    volatile cyg_ucount32 dsr_count CYGBLD_ANNOTATE_VARIABLE_INTR;
194
 
195
    // next DSR in list
196
    Cyg_Interrupt* volatile next_dsr CYGBLD_ANNOTATE_VARIABLE_INTR;
197
 
198
    // static list of pending DSRs
199
    static Cyg_Interrupt* volatile dsr_list[CYGNUM_KERNEL_CPU_MAX]
200
                                           CYGBLD_ANNOTATE_VARIABLE_INTR;
201
 
202
#endif
203
 
204
#ifdef CYGIMP_KERNEL_INTERRUPTS_CHAIN
205
 
206
    // The default mechanism for handling interrupts is to attach just
207
    // one Interrupt object to each vector. In some cases, and on some
208
    // hardware, this is not possible, and each vector must carry a chain
209
    // of interrupts.
210
 
211
    Cyg_Interrupt       *next;          // Next Interrupt in list
212
 
213
    // Chaining ISR inserted in HAL vector
214
    static cyg_uint32 chain_isr(cyg_vector vector, CYG_ADDRWORD data);
215
 
216
    // Table of interrupt chains
217
    static Cyg_Interrupt *chain_list[CYGNUM_HAL_ISR_TABLE_SIZE];
218
 
219
#endif
220
 
221
    // Interrupt disable data. Interrupt disable can be nested. On
222
    // each CPU this is controlled by disable_counter[cpu]. When the
223
    // counter is first incremented from zero to one, the
224
    // interrupt_disable_spinlock is claimed using spin_intsave(), the
225
    // original interrupt enable state being saved in
226
    // interrupt_disable_state[cpu].  When the counter is decremented
227
    // back to zero the spinlock is cleared using clear_intsave().
228
 
229
    // The spinlock is necessary in SMP systems since a thread
230
    // accessing data shared with an ISR may be scheduled on a
231
    // different CPU to the one that handles the interrupt. So, merely
232
    // blocking local interrupts would be ineffective. SMP aware
233
    // device drivers should either use their own spinlocks to protect
234
    // data, or use the API supported by this class, via
235
    // cyg_drv_isr_lock()/_unlock(). Note that it now becomes
236
    // essential that ISRs do this if they are to be SMP-compatible.
237
 
238
    // In a single CPU system, this mechanism reduces to just
239
    // disabling/enabling interrupts.
240
 
241
    // Disable level counter. This counts the number of times
242
    // interrupts have been disabled.
243
    static volatile cyg_int32 disable_counter[CYGNUM_KERNEL_CPU_MAX]
244
                                              CYGBLD_ANNOTATE_VARIABLE_INTR;
245
 
246
    // Interrupt disable spinlock. This is claimed by any CPU that has
247
    // disabled interrupts via the Cyg_Interrupt API.
248
    static Cyg_SpinLock interrupt_disable_spinlock CYGBLD_ANNOTATE_VARIABLE_INTR;
249
 
250
    // Saved interrupt state. When each CPU first disables interrupts
251
    // the original state of the interrupts are saved here to be
252
    // restored later.
253
    static CYG_INTERRUPT_STATE interrupt_disable_state[CYGNUM_KERNEL_CPU_MAX]
254
                                                       CYGBLD_ANNOTATE_VARIABLE_INTR;
255
 
256
 
257
public:
258
 
259
    Cyg_Interrupt                       // Initialize interrupt
260
    (
261
        cyg_vector      vector,         // Vector to attach to
262
        cyg_priority    priority,       // Queue priority
263
        CYG_ADDRWORD    data,           // Data pointer
264
        cyg_ISR         *isr,           // Interrupt Service Routine
265
        cyg_DSR         *dsr            // Deferred Service Routine
266
        );
267
 
268
    ~Cyg_Interrupt();
269
 
270
    // ISR return values
271
    enum {
272
        HANDLED  = 1,                   // Interrupt was handled
273
        CALL_DSR = 2                    // Schedule DSR
274
    };
275
 
276
    // Interrupt management
277
 
278
    void        attach();               // Attach to vector
279
 
280
 
281
    void        detach();               // Detach from vector
282
 
283
 
284
    // Static Interrupt management functions
285
 
286
    // Get the current service routine
287
    static void get_vsr(cyg_vector vector, cyg_VSR **vsr);
288
 
289
    // Install a vector service routine
290
    static void set_vsr(
291
        cyg_vector vector,              // hardware vector to replace
292
        cyg_VSR *vsr,                   // my new service routine
293
        cyg_VSR **old = NULL            // pointer to old vsr, if required
294
        );
295
 
296
 
297
    // Static interrupt masking functions
298
 
299
    // Disable interrupts at the CPU
300
    static void disable_interrupts();
301
 
302
    // Re-enable CPU interrupts
303
    static void enable_interrupts();
304
 
305
    // Are interrupts enabled at the CPU?
306
    static inline cyg_bool interrupts_enabled()
307
    {
308
        return (0 == disable_counter[CYG_KERNEL_CPU_THIS()]);
309
    }
310
 
311
    // Get the vector for the following calls
312
    inline cyg_vector get_vector()
313
    {
314
        return vector;
315
    }
316
 
317
    // Static PIC control functions
318
 
319
    // Mask a specific interrupt in a PIC
320
    static void mask_interrupt(cyg_vector vector);
321
    // The same but not interrupt safe
322
    static void mask_interrupt_intunsafe(cyg_vector vector);
323
 
324
    // Clear PIC mask
325
    static void unmask_interrupt(cyg_vector vector);
326
    // The same but not interrupt safe
327
    static void unmask_interrupt_intunsafe(cyg_vector vector);
328
 
329
    // Acknowledge interrupt at PIC
330
    static void acknowledge_interrupt(cyg_vector vector);
331
 
332
    // Change interrupt detection at PIC
333
    static void configure_interrupt(
334
        cyg_vector vector,              // vector to control
335
        cyg_bool level,                 // level or edge triggered
336
        cyg_bool up                     // hi/lo level, rising/falling edge
337
        );
338
 
339
#ifdef CYGPKG_KERNEL_SMP_SUPPORT
340
 
341
    // SMP support for associating an interrupt with a specific CPU.
342
 
343
    static void set_cpu( cyg_vector, HAL_SMP_CPU_TYPE cpu );
344
    static HAL_SMP_CPU_TYPE get_cpu( cyg_vector );
345
 
346
#endif
347
};
348
 
349
#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS
350
// -------------------------------------------------------------------------
351
// Check for pending DSRs
352
 
353
inline cyg_bool Cyg_Interrupt::DSRs_pending()
354
{
355
    HAL_SMP_CPU_TYPE cpu = CYG_KERNEL_CPU_THIS();
356
#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_TABLE
357
 
358
    return dsr_table_head[cpu] != dsr_table_tail[cpu];
359
 
360
#endif
361
#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST
362
 
363
    return dsr_list[cpu] != NULL;
364
 
365
#endif
366
};
367
#endif // CYGIMP_KERNEL_INTERRUPTS_DSRS
368
 
369
// -------------------------------------------------------------------------
370
#endif // ifndef CYGONCE_KERNEL_INTR_HXX
371
// EOF intr.hxx

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.