1 #ifndef CYGONCE_HAL_HAL_INTR_H
2 #define CYGONCE_HAL_HAL_INTR_H
4 //==========================================================================
8 // HAL Interrupt and clock support
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.
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.
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
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.
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.
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.
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####
47 // Contributors: nickg, jskov,
50 // Purpose: Define Interrupt support
51 // Description: The macros defined here provide the HAL APIs for handling
52 // interrupts and the clock.
55 // #include <cyg/hal/hal_intr.h>
59 //####DESCRIPTIONEND####
61 //==========================================================================
63 #include <pkgconf/hal.h>
65 #include <cyg/infra/cyg_type.h>
66 #include <cyg/hal/hal_io.h>
68 #include <cyg/hal/var_intr.h>
70 //--------------------------------------------------------------------------
73 // These are the exception codes presented in the Cause register and
74 // correspond to VSRs. These values are the ones to use for HAL_VSR_GET/SET
77 #define CYGNUM_HAL_VECTOR_INTERRUPT 0
78 // TLB modification exception
79 #define CYGNUM_HAL_VECTOR_TLB_MOD 1
80 // TLB miss (Load or IFetch)
81 #define CYGNUM_HAL_VECTOR_TLB_LOAD_REFILL 2
83 #define CYGNUM_HAL_VECTOR_TLB_STORE_REFILL 3
84 // Address error (Load or Ifetch)
85 #define CYGNUM_HAL_VECTOR_LOAD_ADDRESS 4
86 // Address error (store)
87 #define CYGNUM_HAL_VECTOR_STORE_ADDRESS 5
89 #define CYGNUM_HAL_VECTOR_IBE 6
90 // Bus error (data load or store)
91 #define CYGNUM_HAL_VECTOR_DBE 7
93 #define CYGNUM_HAL_VECTOR_SYSTEM_CALL 8
95 #define CYGNUM_HAL_VECTOR_BREAKPOINT 9
96 // Reserved instruction
97 #define CYGNUM_HAL_VECTOR_RESERVED_INSTRUCTION 10
98 // Coprocessor unusable
99 #define CYGNUM_HAL_VECTOR_COPROCESSOR 11
100 // Arithmetic overflow
101 #define CYGNUM_HAL_VECTOR_OVERFLOW 12
103 #define CYGNUM_HAL_VECTOR_RESERVED_13 13
104 // Division-by-zero [reserved vector]
105 // This is caused by 'trap 0x7' which GCC puts in the code to check
106 // for division by zero. The break_vsr_springboard in vectors.S is the
107 // only caller of this vector.
108 #define CYGNUM_HAL_VECTOR_DIV_BY_ZERO 14
109 // Floating point exception
110 #ifdef CYGHWR_HAL_MIPS_FPU
111 #define CYGNUM_HAL_VECTOR_FPE 15
114 #define CYGNUM_HAL_VSR_MIN CYGNUM_HAL_VECTOR_INTERRUPT
115 #ifdef CYGNUM_HAL_VECTOR_FPE
116 #define CYGNUM_HAL_VSR_MAX CYGNUM_HAL_VECTOR_FPE
118 #define CYGNUM_HAL_VSR_MAX CYGNUM_HAL_VECTOR_DIV_BY_ZERO
120 #define CYGNUM_HAL_VSR_COUNT (CYGNUM_HAL_VSR_MAX-CYGNUM_HAL_VSR_MIN+1)
122 // Exception vectors. These are the values used when passed out to an
123 // external exception handler using cyg_hal_deliver_exception()
125 #define CYGNUM_HAL_EXCEPTION_DATA_TLBERROR_ACCESS CYGNUM_HAL_VECTOR_TLB_MOD
126 #define CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_ACCESS \
127 CYGNUM_HAL_VECTOR_TLB_LOAD_REFILL
128 #define CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_WRITE \
129 CYGNUM_HAL_VECTOR_TLB_STORE_REFILL
130 #define CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_ACCESS \
131 CYGNUM_HAL_VECTOR_LOAD_ADDRESS
132 #define CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_WRITE \
133 CYGNUM_HAL_VECTOR_STORE_ADDRESS
134 #define CYGNUM_HAL_EXCEPTION_CODE_ACCESS CYGNUM_HAL_VECTOR_IBE
135 #define CYGNUM_HAL_EXCEPTION_DATA_ACCESS CYGNUM_HAL_VECTOR_DBE
136 #define CYGNUM_HAL_EXCEPTION_SYSTEM_CALL CYGNUM_HAL_VECTOR_SYSTEM_CALL
137 #define CYGNUM_HAL_EXCEPTION_INSTRUCTION_BP CYGNUM_HAL_VECTOR_BREAKPOINT
138 #define CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION \
139 CYGNUM_HAL_VECTOR_RESERVED_INSTRUCTION
140 #define CYGNUM_HAL_EXCEPTION_COPROCESSOR CYGNUM_HAL_VECTOR_COPROCESSOR
141 #define CYGNUM_HAL_EXCEPTION_OVERFLOW CYGNUM_HAL_VECTOR_OVERFLOW
142 #define CYGNUM_HAL_EXCEPTION_DIV_BY_ZERO CYGNUM_HAL_VECTOR_DIV_BY_ZERO
143 #ifdef CYGHWR_HAL_MIPS_FPU
144 #define CYGNUM_HAL_EXCEPTION_FPU CYGNUM_HAL_VECTOR_FPE
147 #define CYGNUM_HAL_EXCEPTION_INTERRUPT CYGNUM_HAL_VECTOR_BREAKPOINT
149 #ifdef CYGHWR_HAL_MIPS_FPU
150 // decoded exception vectors
151 #define CYGNUM_HAL_EXCEPTION_FPU_INEXACT (-1)
152 #define CYGNUM_HAL_EXCEPTION_FPU_DIV_BY_ZERO (-2)
153 #define CYGNUM_HAL_EXCEPTION_FPU_OVERFLOW (-3)
154 #define CYGNUM_HAL_EXCEPTION_FPU_UNDERFLOW (-4)
155 #define CYGNUM_HAL_EXCEPTION_FPU_INVALID (-5)
158 // Min/Max exception numbers and how many there are
159 #ifdef CYGNUM_HAL_EXCEPTION_FPU_INVALID
160 #define CYGNUM_HAL_EXCEPTION_MIN CYGNUM_HAL_EXCEPTION_FPU_INVALID
162 #define CYGNUM_HAL_EXCEPTION_MIN CYGNUM_HAL_VSR_MIN
164 #define CYGNUM_HAL_EXCEPTION_MAX CYGNUM_HAL_VSR_MAX
166 #define CYGNUM_HAL_EXCEPTION_COUNT \
167 ( CYGNUM_HAL_EXCEPTION_MAX - CYGNUM_HAL_EXCEPTION_MIN + 1 )
170 #ifndef CYGHWR_HAL_INTERRUPT_VECTORS_DEFINED
172 // the default for all MIPS variants is to use the 6 bits
173 // in the cause register.
175 #define CYGNUM_HAL_INTERRUPT_0 0
176 #define CYGNUM_HAL_INTERRUPT_1 1
177 #define CYGNUM_HAL_INTERRUPT_2 2
178 #define CYGNUM_HAL_INTERRUPT_3 3
179 #define CYGNUM_HAL_INTERRUPT_4 4
180 #define CYGNUM_HAL_INTERRUPT_5 5
182 // Min/Max ISR numbers and how many there are
183 #define CYGNUM_HAL_ISR_MIN 0
184 #define CYGNUM_HAL_ISR_MAX 5
185 #define CYGNUM_HAL_ISR_COUNT 6
187 // The vector used by the Real time clock. The default here is to use
188 // interrupt 5, which is connected to the counter/comparator registers
189 // in many MIPS variants.
191 #ifndef CYGNUM_HAL_INTERRUPT_RTC
192 #define CYGNUM_HAL_INTERRUPT_RTC CYGNUM_HAL_INTERRUPT_5
195 #define CYGHWR_HAL_INTERRUPT_VECTORS_DEFINED
199 //--------------------------------------------------------------------------
200 // Static data used by HAL
203 externC volatile CYG_ADDRESS hal_interrupt_handlers[CYGNUM_HAL_ISR_COUNT];
204 externC volatile CYG_ADDRWORD hal_interrupt_data[CYGNUM_HAL_ISR_COUNT];
205 externC volatile CYG_ADDRESS hal_interrupt_objects[CYGNUM_HAL_ISR_COUNT];
208 externC volatile CYG_ADDRESS hal_vsr_table[CYGNUM_HAL_VSR_MAX+1];
210 //--------------------------------------------------------------------------
212 // The #define is used to test whether this routine exists, and to allow
215 externC cyg_uint32 hal_default_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data);
217 #define HAL_DEFAULT_ISR hal_default_isr
219 //--------------------------------------------------------------------------
220 // Interrupt state storage
222 typedef cyg_uint32 CYG_INTERRUPT_STATE;
224 //--------------------------------------------------------------------------
225 // Interrupt control macros
226 // Beware of nops in this code. They fill delay slots and avoid CP0 hazards
227 // that might otherwise cause following code to run in the wrong state or
228 // cause a resource conflict.
229 #ifndef CYGHWR_HAL_INTERRUPT_ENABLE_DISABLE_RESTORE_DEFINED
231 #define HAL_DISABLE_INTERRUPTS(_old_) \
234 "mfc0 $8,$12; nop;" \
236 "and $8,$8,0XFFFFFFFE;" \
246 #define HAL_ENABLE_INTERRUPTS() \
249 "mfc0 $8,$12; nop;" \
259 #define HAL_RESTORE_INTERRUPTS(_old_) \
262 "mfc0 $8,$12; nop;" \
273 #define HAL_QUERY_INTERRUPTS( _state_ ) \
276 "mfc0 %0,$12; nop;" \
284 #endif // CYGHWR_HAL_INTERRUPT_ENABLE_DISABLE_RESTORE_DEFINED
286 //--------------------------------------------------------------------------
287 // Routine to execute DSRs using separate interrupt stack
289 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
290 externC void hal_interrupt_stack_call_pending_DSRs(void);
291 #define HAL_INTERRUPT_STACK_CALL_PENDING_DSRS() \
292 hal_interrupt_stack_call_pending_DSRs()
294 // these are offered solely for stack usage testing
295 // if they are not defined, then there is no interrupt stack.
296 #define HAL_INTERRUPT_STACK_BASE cyg_interrupt_stack_base
297 #define HAL_INTERRUPT_STACK_TOP cyg_interrupt_stack
298 // use them to declare these extern however you want:
299 // extern char HAL_INTERRUPT_STACK_BASE[];
300 // extern char HAL_INTERRUPT_STACK_TOP[];
304 //--------------------------------------------------------------------------
305 // Vector translation.
306 // For chained interrupts we only have a single vector though which all
307 // are passed. For unchained interrupts we have a vector per interrupt.
309 #ifndef HAL_TRANSLATE_VECTOR
311 #if defined(CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN)
313 #define HAL_TRANSLATE_VECTOR(_vector_,_index_) (_index_) = 0
317 #define HAL_TRANSLATE_VECTOR(_vector_,_index_) (_index_) = (_vector_)
323 //--------------------------------------------------------------------------
324 // Interrupt and VSR attachment macros
326 #define HAL_INTERRUPT_IN_USE( _vector_, _state_) \
328 cyg_uint32 _index_; \
329 HAL_TRANSLATE_VECTOR ((_vector_), _index_); \
331 if( hal_interrupt_handlers[_index_] == (CYG_ADDRESS)HAL_DEFAULT_ISR ) \
337 #define HAL_INTERRUPT_ATTACH( _vector_, _isr_, _data_, _object_ ) \
339 cyg_uint32 _index_; \
340 HAL_TRANSLATE_VECTOR( _vector_, _index_ ); \
342 if( hal_interrupt_handlers[_index_] == (CYG_ADDRESS)HAL_DEFAULT_ISR ) \
344 hal_interrupt_handlers[_index_] = (CYG_ADDRESS)_isr_; \
345 hal_interrupt_data[_index_] = (CYG_ADDRWORD)_data_; \
346 hal_interrupt_objects[_index_] = (CYG_ADDRESS)_object_; \
350 #define HAL_INTERRUPT_DETACH( _vector_, _isr_ ) \
352 cyg_uint32 _index_; \
353 HAL_TRANSLATE_VECTOR( _vector_, _index_ ); \
355 if( hal_interrupt_handlers[_index_] == (CYG_ADDRESS)_isr_ ) \
357 hal_interrupt_handlers[_index_] = (CYG_ADDRESS)HAL_DEFAULT_ISR; \
358 hal_interrupt_data[_index_] = 0; \
359 hal_interrupt_objects[_index_] = 0; \
363 #define HAL_VSR_GET( _vector_, _pvsr_ ) \
364 *(_pvsr_) = (void (*)())hal_vsr_table[_vector_];
367 #define HAL_VSR_SET( _vector_, _vsr_, _poldvsr_ ) CYG_MACRO_START \
368 if( (void*)_poldvsr_ != NULL) \
369 *(CYG_ADDRESS *)_poldvsr_ = (CYG_ADDRESS)hal_vsr_table[_vector_]; \
370 hal_vsr_table[_vector_] = (CYG_ADDRESS)_vsr_; \
373 // This is an ugly name, but what it means is: grab the VSR back to eCos
374 // internal handling, or if you like, the default handler. But if
375 // cooperating with GDB and CygMon, the default behaviour is to pass most
376 // exceptions to CygMon. This macro undoes that so that eCos handles the
377 // exception. So use it with care.
379 externC void __default_exception_vsr(void);
380 externC void __default_interrupt_vsr(void);
381 externC void __break_vsr_springboard(void);
383 #define HAL_VSR_SET_TO_ECOS_HANDLER( _vector_, _poldvsr_ ) CYG_MACRO_START \
384 HAL_VSR_SET( _vector_, _vector_ == CYGNUM_HAL_VECTOR_INTERRUPT \
385 ? (CYG_ADDRESS)__default_interrupt_vsr \
386 : _vector_ == CYGNUM_HAL_VECTOR_BREAKPOINT \
387 ? (CYG_ADDRESS)__break_vsr_springboard \
388 : (CYG_ADDRESS)__default_exception_vsr, \
392 //--------------------------------------------------------------------------
393 // Interrupt controller access
394 // The default code here simply uses the fields present in the CP0 status
395 // and cause registers to implement this functionality.
396 // Beware of nops in this code. They fill delay slots and avoid CP0 hazards
397 // that might otherwise cause following code to run in the wrong state or
398 // cause a resource conflict.
400 #ifndef CYGHWR_HAL_INTERRUPT_CONTROLLER_ACCESS_DEFINED
402 #define HAL_INTERRUPT_MASK( _vector_ ) \
406 "la $2,0x00000400\n" \
418 #define HAL_INTERRUPT_UNMASK( _vector_ ) \
422 "la $2,0x00000400\n" \
433 #define HAL_INTERRUPT_ACKNOWLEDGE( _vector_ ) \
437 "la $2,0x00000400\n" \
449 #define HAL_INTERRUPT_CONFIGURE( _vector_, _level_, _up_ )
451 #define HAL_INTERRUPT_SET_LEVEL( _vector_, _level_ )
453 #define CYGHWR_HAL_INTERRUPT_CONTROLLER_ACCESS_DEFINED
457 //--------------------------------------------------------------------------
459 // This code uses the count and compare registers that are present in many
461 // Beware of nops in this code. They fill delay slots and avoid CP0 hazards
462 // that might otherwise cause following code to run in the wrong state or
463 // cause a resource conflict.
465 #ifndef CYGHWR_HAL_CLOCK_CONTROL_DEFINED
467 externC CYG_WORD32 cyg_hal_clock_period;
468 #define CYGHWR_HAL_CLOCK_PERIOD_DEFINED
470 #define HAL_CLOCK_INITIALIZE( _period_ ) \
480 cyg_hal_clock_period = _period_; \
483 #define HAL_CLOCK_RESET( _vector_, _period_ ) \
495 #define HAL_CLOCK_READ( _pvalue_ ) \
497 register CYG_WORD32 result; \
502 *(_pvalue_) = result; \
505 #define CYGHWR_HAL_CLOCK_CONTROL_DEFINED
509 #if defined(CYGVAR_KERNEL_COUNTERS_CLOCK_LATENCY) && \
510 !defined(HAL_CLOCK_LATENCY)
511 #define HAL_CLOCK_LATENCY( _pvalue_ ) \
513 register CYG_WORD32 _cval_; \
514 HAL_CLOCK_READ(&_cval_); \
515 *(_pvalue_) = _cval_ - cyg_hal_clock_period; \
520 //--------------------------------------------------------------------------
521 // Microsecond delay function provided in hal_misc.c
522 externC void hal_delay_us(int us);
524 #define HAL_DELAY_US(n) hal_delay_us(n)
526 //--------------------------------------------------------------------------
527 #endif // ifndef CYGONCE_HAL_HAL_INTR_H