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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [kernel/] [current/] [include/] [intr.hxx] - Blame information for rev 786

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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