1 //==========================================================================
5 // Interrupt class implementations
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
41 //#####DESCRIPTIONBEGIN####
44 // Contributors: nickg
46 // Purpose: Interrupt class implementation
47 // Description: This file contains the definitions of the interrupt
50 //####DESCRIPTIONEND####
52 //==========================================================================
54 #include <pkgconf/kernel.h>
56 #include <cyg/kernel/ktypes.h> // base kernel types
57 #include <cyg/infra/cyg_trac.h> // tracing macros
58 #include <cyg/infra/cyg_ass.h> // assertion macros
59 #include <cyg/kernel/instrmnt.h> // instrumentation
61 #include <cyg/kernel/intr.hxx> // our header
63 #include <cyg/kernel/sched.hxx> // scheduler
65 #include <cyg/kernel/sched.inl>
67 // -------------------------------------------------------------------------
70 volatile cyg_int32 Cyg_Interrupt::disable_counter[CYGNUM_KERNEL_CPU_MAX];
72 Cyg_SpinLock Cyg_Interrupt::interrupt_disable_spinlock CYG_INIT_PRIORITY( INTERRUPTS );
74 CYG_INTERRUPT_STATE Cyg_Interrupt::interrupt_disable_state[CYGNUM_KERNEL_CPU_MAX];
76 // -------------------------------------------------------------------------
78 Cyg_Interrupt::Cyg_Interrupt(
79 cyg_vector vec, // Vector to attach to
80 cyg_priority pri, // Queue priority
81 CYG_ADDRWORD d, // Data pointer
82 cyg_ISR *ir, // Interrupt Service Routine
83 cyg_DSR *dr // Deferred Service Routine
86 CYG_REPORT_FUNCTION();
87 CYG_REPORT_FUNCARG5("vector=%d, priority=%d, data=%08x, isr=%08x, "
88 "dsr=%08x", vec, pri, d, ir, dr);
96 #ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST
103 #ifdef CYGIMP_KERNEL_INTERRUPTS_CHAIN
113 // -------------------------------------------------------------------------
115 Cyg_Interrupt::~Cyg_Interrupt()
117 CYG_REPORT_FUNCTION();
122 // -------------------------------------------------------------------------
123 // DSR handling statics:
125 #ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_TABLE
128 Cyg_Interrupt::dsr_table[CYGNUM_KERNEL_CPU_MAX][CYGNUM_KERNEL_INTERRUPTS_DSRS_TABLE_SIZE];
130 cyg_ucount32 Cyg_Interrupt::dsr_table_head[CYGNUM_KERNEL_CPU_MAX];
132 volatile cyg_ucount32 Cyg_Interrupt::dsr_table_tail[CYGNUM_KERNEL_CPU_MAX];
136 #ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST
138 Cyg_Interrupt* volatile Cyg_Interrupt::dsr_list[CYGNUM_KERNEL_CPU_MAX];
140 # ifdef CYGSEM_KERNEL_INTERRUPTS_DSRS_LIST_FIFO
141 Cyg_Interrupt* volatile Cyg_Interrupt::dsr_list_tail[CYGNUM_KERNEL_CPU_MAX];
146 // -------------------------------------------------------------------------
147 // Call any pending DSRs
150 Cyg_Interrupt::call_pending_DSRs_inner(void)
152 // CYG_REPORT_FUNCTION();
154 HAL_SMP_CPU_TYPE cpu = CYG_KERNEL_CPU_THIS();
156 #ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_TABLE
158 while( dsr_table_head[cpu] != dsr_table_tail[cpu] )
160 Cyg_Interrupt *intr = dsr_table[cpu][dsr_table_head[cpu]];
162 dsr_table_head[cpu]++;
163 if( dsr_table_head[cpu] >= CYGNUM_KERNEL_INTERRUPTS_DSRS_TABLE_SIZE )
164 dsr_table_head[cpu] = 0;
166 CYG_INSTRUMENT_INTR(CALL_DSR, intr->vector, 0);
168 CYG_ASSERT( intr->dsr != NULL , "No DSR defined");
170 intr->dsr( intr->vector, 1, (CYG_ADDRWORD)intr->data );
175 #ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST
177 # ifdef CYGSEM_KERNEL_INTERRUPTS_DSRS_LIST_FIFO
180 HAL_DISABLE_INTERRUPTS(old_intr);
181 Cyg_Interrupt* intr = dsr_list[cpu];
182 CYG_ASSERT(intr != 0, "No DSRs are pended");
184 dsr_list_tail[cpu] = 0;
187 cyg_count32 count = intr->dsr_count;
188 Cyg_Interrupt* next = intr->next_dsr;
191 HAL_RESTORE_INTERRUPTS(old_intr);
193 CYG_ASSERT(intr->dsr != 0, "No DSR defined");
194 CYG_ASSERT(count > 0, "DSR posted but post count is zero");
195 intr->dsr(intr->vector, count, (CYG_ADDRWORD)intr->data);
201 HAL_DISABLE_INTERRUPTS(old_intr);
204 # else // ! defined CYGSEM_KERNEL_INTERRUPTS_DSRS_LIST_FIFO
206 while( dsr_list[cpu] != NULL )
212 HAL_DISABLE_INTERRUPTS(old_intr);
214 intr = dsr_list[cpu];
215 dsr_list[cpu] = intr->next_dsr;
216 count = intr->dsr_count;
219 HAL_RESTORE_INTERRUPTS(old_intr);
221 CYG_ASSERT( intr->dsr != NULL , "No DSR defined");
223 intr->dsr( intr->vector, count, (CYG_ADDRWORD)intr->data );
227 # endif // ! defined CYGSEM_KERNEL_INTERRUPTS_DSRS_LIST_FIFO
229 #endif // defined CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST
234 cyg_interrupt_call_pending_DSRs(void)
236 Cyg_Interrupt::call_pending_DSRs_inner();
240 // Use HAL supported function to run through the DSRs, but executing using
241 // the separate interrupt stack if available. This function calls back
242 // into this module via 'cyg_interrupt_call_pending_DSRs' above, to keep
243 // the whole process as general as possible.
246 Cyg_Interrupt::call_pending_DSRs(void)
248 CYG_ASSERT( Cyg_Scheduler::get_sched_lock() == 1,
249 "DSRs being called with sched_lock not equal to 1");
250 HAL_INTERRUPT_STACK_CALL_PENDING_DSRS();
254 // -------------------------------------------------------------------------
257 Cyg_Interrupt::post_dsr(void)
259 // CYG_REPORT_FUNCTION();
260 HAL_SMP_CPU_TYPE cpu = CYG_KERNEL_CPU_THIS();
262 CYG_INSTRUMENT_INTR(POST_DSR, vector, 0);
266 // We need to disable interrupts during this part to
267 // guard against nested interrupts.
269 HAL_DISABLE_INTERRUPTS(old_intr);
271 #ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_TABLE
273 dsr_table[cpu][dsr_table_tail[cpu]++] = this;
274 if( dsr_table_tail[cpu] >= CYGNUM_KERNEL_INTERRUPTS_DSRS_TABLE_SIZE )
275 dsr_table_tail[cpu] = 0;
279 #ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST
281 // Only add the interrupt to the dsr list if this is
282 // the first DSR call.
283 if( dsr_count++ == 0 )
285 # ifdef CYGSEM_KERNEL_INTERRUPTS_DSRS_LIST_FIFO
287 // Add to the tail of the list.
288 Cyg_Interrupt* tail = dsr_list_tail[cpu];
289 dsr_list_tail[cpu] = this;
292 CYG_ASSERT( 0 != dsr_list[cpu] ,
293 "DSR list is not empty but its head is 0");
294 tail->next_dsr = this;
298 CYG_ASSERT( 0 == dsr_list[cpu] ,
299 "DSR list tail is 0 but its head is not");
300 dsr_list[cpu] = this;
303 # else // ! defined CYGSEM_KERNEL_INTERRUPTS_DSRS_LIST_FIFO
305 // At present DSRs are pushed onto the list and will be called
306 // in reverse order. We do not define the order in which DSRs
307 // are called, so this is acceptable.
308 next_dsr = dsr_list[cpu];
309 dsr_list[cpu] = this;
311 # endif // ! defined CYGSEM_KERNEL_INTERRUPTS_DSRS_LIST_FIFO
315 #endif // defined CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST
317 HAL_RESTORE_INTERRUPTS(old_intr);
320 // -------------------------------------------------------------------------
321 // A C callable interface to Cyg_Interrupt::post_dsr() that can be used from
325 cyg_interrupt_post_dsr( CYG_ADDRWORD intr_obj )
327 Cyg_Interrupt* intr = (Cyg_Interrupt*) intr_obj;
331 // -------------------------------------------------------------------------
333 // FIXME: should have better name - Jifl
338 HAL_SavedRegisters *regs
341 // CYG_REPORT_FUNCTION();
343 #ifdef CYGPKG_KERNEL_SMP_SUPPORT
344 Cyg_Scheduler::lock();
347 // Sometimes we have a NULL intr object pointer.
348 cyg_vector vector = (intr!=NULL)?intr->vector:0;
350 CYG_INSTRUMENT_INTR(END, vector, isr_ret);
352 CYG_UNUSED_PARAM( cyg_vector, vector ); // prevent compiler warning
354 #ifndef CYGIMP_KERNEL_INTERRUPTS_CHAIN
356 // Only do this if we are in a non-chained configuration.
357 // If we are chained, then chain_isr below will do the DSR
360 if( isr_ret & Cyg_Interrupt::CALL_DSR && intr != NULL ) intr->post_dsr();
364 #ifdef CYGDBG_KERNEL_DEBUG_GDB_THREAD_SUPPORT
366 // If we have GDB support enabled, and there is the possibility
367 // that this thread will be context switched as a result of this
368 // interrupt, then save the pointer to the saved thread context in
369 // the thread object so that GDB can get a meaningful context to
372 Cyg_Scheduler::get_current_thread()->set_saved_context(regs);
376 // Now unlock the scheduler, which may also call DSRs
377 // and cause a thread switch to happen.
379 Cyg_Scheduler::unlock();
381 #ifdef CYGDBG_KERNEL_DEBUG_GDB_THREAD_SUPPORT
383 Cyg_Scheduler::get_current_thread()->set_saved_context(0);
387 CYG_INSTRUMENT_INTR(RESTORE, vector, 0);
390 // -------------------------------------------------------------------------
391 // Interrupt chaining statics.
393 #ifdef CYGIMP_KERNEL_INTERRUPTS_CHAIN
395 Cyg_Interrupt *Cyg_Interrupt::chain_list[CYGNUM_HAL_ISR_TABLE_SIZE];
399 // -------------------------------------------------------------------------
400 // Chaining ISR inserted in HAL vector
402 #ifdef CYGIMP_KERNEL_INTERRUPTS_CHAIN
405 Cyg_Interrupt::chain_isr(cyg_vector vector, CYG_ADDRWORD data)
407 Cyg_Interrupt *p = *(Cyg_Interrupt **)data;
408 register cyg_uint32 isr_ret = 0;
409 register cyg_uint32 isr_chain_ret = 0;
411 CYG_INSTRUMENT_INTR(CHAIN_ISR, vector, 0);
415 if( p->vector == vector )
417 isr_ret = p->isr(vector, p->data);
419 isr_chain_ret |= isr_ret;
421 if( isr_ret & Cyg_Interrupt::CALL_DSR ) p->post_dsr();
423 if( isr_ret & Cyg_Interrupt::HANDLED ) break;
429 #ifdef HAL_DEFAULT_ISR
430 if( (isr_chain_ret & (Cyg_Interrupt::HANDLED|Cyg_Interrupt::CALL_DSR)) == 0 )
432 // If we finished the loop for some reason other than that an
433 // ISR has handled the interrupt, call any default ISR to either
434 // report the spurious interrupt, or do some other HAL level processing
435 // such as GDB interrupt detection etc.
437 HAL_DEFAULT_ISR( vector, 0 );
441 return isr_ret & ~Cyg_Interrupt::CALL_DSR;
446 // -------------------------------------------------------------------------
447 // Attach an ISR to an interrupt vector.
450 Cyg_Interrupt::attach(void)
452 CYG_REPORT_FUNCTION();
454 CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
455 CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
457 CYG_INSTRUMENT_INTR(ATTACH, vector, 0);
459 HAL_INTERRUPT_SET_LEVEL( vector, priority );
461 #ifdef CYGIMP_KERNEL_INTERRUPTS_CHAIN
463 CYG_ASSERT( next == NULL , "Cyg_Interrupt already on a list");
467 HAL_TRANSLATE_VECTOR( vector, index );
469 if( chain_list[index] == NULL )
472 // First Interrupt on this chain, just assign it and register
473 // the chain_isr with the HAL.
475 chain_list[index] = this;
477 HAL_INTERRUPT_IN_USE( vector, in_use );
478 CYG_ASSERT( 0 == in_use, "Interrupt vector not free.");
479 HAL_INTERRUPT_ATTACH( vector, chain_isr, &chain_list[index], NULL );
483 // There are already interrupts chained, add this one into the
484 // chain in priority order.
486 Cyg_Interrupt **p = &chain_list[index];
490 Cyg_Interrupt *n = *p;
492 if( n->priority < priority ) break;
506 HAL_INTERRUPT_IN_USE( vector, in_use );
507 CYG_ASSERT( 0 == in_use, "Interrupt vector not free.");
509 HAL_INTERRUPT_ATTACH( vector, isr, data, this );
516 // -------------------------------------------------------------------------
517 // Detach the ISR from the vector
520 Cyg_Interrupt::detach(void)
522 CYG_REPORT_FUNCTION();
524 CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
525 CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
527 CYG_INSTRUMENT_INTR(DETACH, vector, 0);
529 #ifdef CYGIMP_KERNEL_INTERRUPTS_CHAIN
531 // Remove the interrupt object from the vector chain.
535 HAL_TRANSLATE_VECTOR( vector, index );
537 Cyg_Interrupt **p = &chain_list[index];
541 Cyg_Interrupt *n = *p;
552 // If this was the last one, detach the vector.
554 if( chain_list[index] == NULL )
555 HAL_INTERRUPT_DETACH( vector, chain_isr );
559 HAL_INTERRUPT_DETACH( vector, isr );
567 // -------------------------------------------------------------------------
568 // Get the current service routine
571 Cyg_Interrupt::get_vsr(cyg_vector vector, cyg_VSR **vsr)
573 CYG_REPORT_FUNCTION();
574 CYG_REPORT_FUNCARG2("vector = %d, mem to put VSR in is at %08x", vector,
577 CYG_ASSERT( vector >= CYGNUM_HAL_VSR_MIN, "Invalid vector");
578 CYG_ASSERT( vector <= CYGNUM_HAL_VSR_MAX, "Invalid vector");
580 HAL_VSR_GET( vector, vsr );
585 // -------------------------------------------------------------------------
586 // Install a vector service routine
589 Cyg_Interrupt::set_vsr(cyg_vector vector, cyg_VSR *vsr, cyg_VSR **old)
591 CYG_REPORT_FUNCTION();
593 CYG_REPORT_FUNCARG3( "vector = %d, new vsr is at %08x, mem to put "
594 "old VSR in is at %08x", vector, vsr, old);
596 CYG_INSTRUMENT_INTR(SET_VSR, vector, vsr);
598 CYG_ASSERT( vector >= CYGNUM_HAL_VSR_MIN, "Invalid vector");
599 CYG_ASSERT( vector <= CYGNUM_HAL_VSR_MAX, "Invalid vector");
601 CYG_INTERRUPT_STATE old_ints;
603 HAL_DISABLE_INTERRUPTS(old_ints);
605 HAL_VSR_SET( vector, vsr, old );
607 HAL_RESTORE_INTERRUPTS(old_ints);
612 // -------------------------------------------------------------------------
613 // Disable interrupts at the CPU
617 Cyg_Interrupt::disable_interrupts(void)
619 CYG_REPORT_FUNCTION();
621 CYG_INSTRUMENT_INTR(DISABLE, disable_counter[CYG_KERNEL_CPU_THIS()]+1, 0);
623 HAL_SMP_CPU_TYPE cpu_this = CYG_KERNEL_CPU_THIS();
625 // If the disable_counter is zero, disable interrupts and claim the spinlock.
627 if( 0 == disable_counter[cpu_this] )
629 // Claim the spinlock and disable interrupts. We save the original interrupt
630 // enable state to restore later.
631 interrupt_disable_spinlock.spin_intsave(&interrupt_disable_state[cpu_this]);
634 // Now increment our disable counter.
636 disable_counter[cpu_this]++;
642 // -------------------------------------------------------------------------
643 // Re-enable CPU interrupts
646 Cyg_Interrupt::enable_interrupts(void)
648 CYG_REPORT_FUNCTION();
650 CYG_INSTRUMENT_INTR(ENABLE, disable_counter[CYG_KERNEL_CPU_THIS()], 0);
652 HAL_SMP_CPU_TYPE cpu_this = CYG_KERNEL_CPU_THIS();
654 CYG_ASSERT( disable_counter[cpu_this] > 0 , "Disable counter not greater than zero");
656 // If the disable counter goes to zero, then release the spinlock and restore
657 // the previous interrupt state.
659 if( --disable_counter[cpu_this] == 0 )
661 interrupt_disable_spinlock.clear_intsave(interrupt_disable_state[cpu_this]);
667 // -------------------------------------------------------------------------
668 // Mask a specific interrupt in a PIC
671 Cyg_Interrupt::mask_interrupt(cyg_vector vector)
673 CYG_REPORT_FUNCTION();
674 CYG_REPORT_FUNCARG1("vector=%d", vector);
676 CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
677 CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
679 CYG_INSTRUMENT_INTR(MASK, vector, 0);
681 CYG_INTERRUPT_STATE old_ints;
683 HAL_DISABLE_INTERRUPTS(old_ints);
684 HAL_INTERRUPT_MASK( vector );
685 HAL_RESTORE_INTERRUPTS(old_ints);
690 // -------------------------------------------------------------------------
691 // Mask a specific interrupt in a PIC (but not interrupt safe)
694 Cyg_Interrupt::mask_interrupt_intunsafe(cyg_vector vector)
696 CYG_REPORT_FUNCTION();
697 CYG_REPORT_FUNCARG1("vector=%d", vector);
700 CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
701 CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
703 CYG_INSTRUMENT_INTR(MASK, vector, 0);
705 HAL_INTERRUPT_MASK( vector );
710 // -------------------------------------------------------------------------
714 Cyg_Interrupt::unmask_interrupt(cyg_vector vector)
716 CYG_REPORT_FUNCTION();
718 CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
719 CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
721 CYG_INSTRUMENT_INTR(UNMASK, vector, 0);
723 CYG_INTERRUPT_STATE old_ints;
725 HAL_DISABLE_INTERRUPTS(old_ints);
726 HAL_INTERRUPT_UNMASK( vector );
727 HAL_RESTORE_INTERRUPTS(old_ints);
733 // -------------------------------------------------------------------------
734 // Clear PIC mask (but not interrupt safe)
737 Cyg_Interrupt::unmask_interrupt_intunsafe(cyg_vector vector)
739 CYG_REPORT_FUNCTION();
741 CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
742 CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
744 CYG_INSTRUMENT_INTR(UNMASK, vector, 0);
746 HAL_INTERRUPT_UNMASK( vector );
752 // -------------------------------------------------------------------------
753 // Acknowledge interrupt at PIC
756 Cyg_Interrupt::acknowledge_interrupt(cyg_vector vector)
758 // CYG_REPORT_FUNCTION();
760 CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
761 CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
763 CYG_INSTRUMENT_INTR(ACK, vector, 0);
765 HAL_INTERRUPT_ACKNOWLEDGE( vector );
768 // -------------------------------------------------------------------------
769 // Change interrupt detection at PIC
772 Cyg_Interrupt::configure_interrupt(
773 cyg_vector vector, // vector to control
774 cyg_bool level, // level or edge triggered
775 cyg_bool up // hi/lo level, rising/falling edge
778 CYG_REPORT_FUNCTION();
779 CYG_REPORT_FUNCARG3("vector = %d, level = %d, up = %d", vector, level,
782 CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
783 CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
785 CYG_INSTRUMENT_INTR(CONFIGURE, vector, (level<<1)|up);
787 HAL_INTERRUPT_CONFIGURE( vector, level, up );
792 // -------------------------------------------------------------------------
793 // SMP support for setting/getting interrupt CPU
795 #ifdef CYGPKG_KERNEL_SMP_SUPPORT
798 Cyg_Interrupt::set_cpu(
799 cyg_vector vector, // vector to control
800 HAL_SMP_CPU_TYPE cpu // CPU to set
803 CYG_REPORT_FUNCTION();
804 CYG_REPORT_FUNCARG2("vector = %d, cpu = %d", vector, cpu );
806 CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
807 CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
809 CYG_INSTRUMENT_INTR(SET_CPU, vector, cpu);
811 HAL_INTERRUPT_SET_CPU( vector, cpu );
817 Cyg_Interrupt::get_cpu(
818 cyg_vector vector // vector to control
821 CYG_REPORT_FUNCTION();
822 CYG_REPORT_FUNCARG1("vector = %d", vector);
824 CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
825 CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
827 HAL_SMP_CPU_TYPE cpu = 0;
829 HAL_INTERRUPT_GET_CPU( vector, cpu );
831 CYG_INSTRUMENT_INTR(GET_CPU, vector, cpu);
840 // -------------------------------------------------------------------------