//==========================================================================
|
//==========================================================================
|
//
|
//
|
// intr/intr.cxx
|
// intr/intr.cxx
|
//
|
//
|
// Interrupt class implementations
|
// Interrupt class implementations
|
//
|
//
|
//==========================================================================
|
//==========================================================================
|
//####ECOSGPLCOPYRIGHTBEGIN####
|
//####ECOSGPLCOPYRIGHTBEGIN####
|
// -------------------------------------------
|
// -------------------------------------------
|
// This file is part of eCos, the Embedded Configurable Operating System.
|
// This file is part of eCos, the Embedded Configurable Operating System.
|
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
|
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
|
//
|
//
|
// eCos is free software; you can redistribute it and/or modify it under
|
// eCos is free software; you can redistribute it and/or modify it under
|
// the terms of the GNU General Public License as published by the Free
|
// the terms of the GNU General Public License as published by the Free
|
// Software Foundation; either version 2 or (at your option) any later version.
|
// Software Foundation; either version 2 or (at your option) any later version.
|
//
|
//
|
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
|
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
|
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
// for more details.
|
// for more details.
|
//
|
//
|
// You should have received a copy of the GNU General Public License along
|
// You should have received a copy of the GNU General Public License along
|
// with eCos; if not, write to the Free Software Foundation, Inc.,
|
// with eCos; if not, write to the Free Software Foundation, Inc.,
|
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
//
|
//
|
// As a special exception, if other files instantiate templates or use macros
|
// As a special exception, if other files instantiate templates or use macros
|
// or inline functions from this file, or you compile this file and link it
|
// or inline functions from this file, or you compile this file and link it
|
// with other works to produce a work based on this file, this file does not
|
// with other works to produce a work based on this file, this file does not
|
// by itself cause the resulting work to be covered by the GNU General Public
|
// by itself cause the resulting work to be covered by the GNU General Public
|
// License. However the source code for this file must still be made available
|
// License. However the source code for this file must still be made available
|
// in accordance with section (3) of the GNU General Public License.
|
// in accordance with section (3) of the GNU General Public License.
|
//
|
//
|
// This exception does not invalidate any other reasons why a work based on
|
// This exception does not invalidate any other reasons why a work based on
|
// this file might be covered by the GNU General Public License.
|
// this file might be covered by the GNU General Public License.
|
//
|
//
|
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
|
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
|
// at http://sources.redhat.com/ecos/ecos-license/
|
// at http://sources.redhat.com/ecos/ecos-license/
|
// -------------------------------------------
|
// -------------------------------------------
|
//####ECOSGPLCOPYRIGHTEND####
|
//####ECOSGPLCOPYRIGHTEND####
|
//==========================================================================
|
//==========================================================================
|
//#####DESCRIPTIONBEGIN####
|
//#####DESCRIPTIONBEGIN####
|
//
|
//
|
// Author(s): nickg
|
// Author(s): nickg
|
// Contributors: nickg
|
// Contributors: nickg
|
// Date: 1999-02-17
|
// Date: 1999-02-17
|
// Purpose: Interrupt class implementation
|
// Purpose: Interrupt class implementation
|
// Description: This file contains the definitions of the interrupt
|
// Description: This file contains the definitions of the interrupt
|
// class.
|
// class.
|
//
|
//
|
//####DESCRIPTIONEND####
|
//####DESCRIPTIONEND####
|
//
|
//
|
//==========================================================================
|
//==========================================================================
|
|
|
#include <pkgconf/kernel.h>
|
#include <pkgconf/kernel.h>
|
|
|
#include <cyg/kernel/ktypes.h> // base kernel types
|
#include <cyg/kernel/ktypes.h> // base kernel types
|
#include <cyg/infra/cyg_trac.h> // tracing macros
|
#include <cyg/infra/cyg_trac.h> // tracing macros
|
#include <cyg/infra/cyg_ass.h> // assertion macros
|
#include <cyg/infra/cyg_ass.h> // assertion macros
|
#include <cyg/kernel/instrmnt.h> // instrumentation
|
#include <cyg/kernel/instrmnt.h> // instrumentation
|
|
|
#include <cyg/kernel/intr.hxx> // our header
|
#include <cyg/kernel/intr.hxx> // our header
|
|
|
#include <cyg/kernel/sched.hxx> // scheduler
|
#include <cyg/kernel/sched.hxx> // scheduler
|
|
|
#include <cyg/kernel/sched.inl>
|
#include <cyg/kernel/sched.inl>
|
|
|
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
// Statics
|
// Statics
|
|
|
volatile cyg_int32 Cyg_Interrupt::disable_counter[CYGNUM_KERNEL_CPU_MAX];
|
volatile cyg_int32 Cyg_Interrupt::disable_counter[CYGNUM_KERNEL_CPU_MAX];
|
|
|
Cyg_SpinLock Cyg_Interrupt::interrupt_disable_spinlock CYG_INIT_PRIORITY( INTERRUPTS );
|
Cyg_SpinLock Cyg_Interrupt::interrupt_disable_spinlock CYG_INIT_PRIORITY( INTERRUPTS );
|
|
|
CYG_INTERRUPT_STATE Cyg_Interrupt::interrupt_disable_state[CYGNUM_KERNEL_CPU_MAX];
|
CYG_INTERRUPT_STATE Cyg_Interrupt::interrupt_disable_state[CYGNUM_KERNEL_CPU_MAX];
|
|
|
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
|
|
Cyg_Interrupt::Cyg_Interrupt(
|
Cyg_Interrupt::Cyg_Interrupt(
|
cyg_vector vec, // Vector to attach to
|
cyg_vector vec, // Vector to attach to
|
cyg_priority pri, // Queue priority
|
cyg_priority pri, // Queue priority
|
CYG_ADDRWORD d, // Data pointer
|
CYG_ADDRWORD d, // Data pointer
|
cyg_ISR *ir, // Interrupt Service Routine
|
cyg_ISR *ir, // Interrupt Service Routine
|
cyg_DSR *dr // Deferred Service Routine
|
cyg_DSR *dr // Deferred Service Routine
|
)
|
)
|
{
|
{
|
CYG_REPORT_FUNCTION();
|
CYG_REPORT_FUNCTION();
|
CYG_REPORT_FUNCARG5("vector=%d, priority=%d, data=%08x, isr=%08x, "
|
CYG_REPORT_FUNCARG5("vector=%d, priority=%d, data=%08x, isr=%08x, "
|
"dsr=%08x", vec, pri, d, ir, dr);
|
"dsr=%08x", vec, pri, d, ir, dr);
|
|
|
vector = vec;
|
vector = vec;
|
priority = pri;
|
priority = pri;
|
isr = ir;
|
isr = ir;
|
dsr = dr;
|
dsr = dr;
|
data = d;
|
data = d;
|
|
|
#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST
|
#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST
|
|
|
dsr_count = 0;
|
dsr_count = 0;
|
next_dsr = NULL;
|
next_dsr = NULL;
|
|
|
#endif
|
#endif
|
|
|
#ifdef CYGIMP_KERNEL_INTERRUPTS_CHAIN
|
#ifdef CYGIMP_KERNEL_INTERRUPTS_CHAIN
|
|
|
next = NULL;
|
next = NULL;
|
|
|
#endif
|
#endif
|
|
|
CYG_REPORT_RETURN();
|
CYG_REPORT_RETURN();
|
|
|
};
|
};
|
|
|
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
|
|
Cyg_Interrupt::~Cyg_Interrupt()
|
Cyg_Interrupt::~Cyg_Interrupt()
|
{
|
{
|
CYG_REPORT_FUNCTION();
|
CYG_REPORT_FUNCTION();
|
detach();
|
detach();
|
CYG_REPORT_RETURN();
|
CYG_REPORT_RETURN();
|
};
|
};
|
|
|
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
// DSR handling statics:
|
// DSR handling statics:
|
|
|
#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_TABLE
|
#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_TABLE
|
|
|
Cyg_Interrupt *
|
Cyg_Interrupt *
|
Cyg_Interrupt::dsr_table[CYGNUM_KERNEL_CPU_MAX][CYGNUM_KERNEL_INTERRUPTS_DSRS_TABLE_SIZE];
|
Cyg_Interrupt::dsr_table[CYGNUM_KERNEL_CPU_MAX][CYGNUM_KERNEL_INTERRUPTS_DSRS_TABLE_SIZE];
|
|
|
cyg_ucount32 Cyg_Interrupt::dsr_table_head[CYGNUM_KERNEL_CPU_MAX];
|
cyg_ucount32 Cyg_Interrupt::dsr_table_head[CYGNUM_KERNEL_CPU_MAX];
|
|
|
volatile cyg_ucount32 Cyg_Interrupt::dsr_table_tail[CYGNUM_KERNEL_CPU_MAX];
|
volatile cyg_ucount32 Cyg_Interrupt::dsr_table_tail[CYGNUM_KERNEL_CPU_MAX];
|
|
|
#endif
|
#endif
|
|
|
#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST
|
#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST
|
|
|
Cyg_Interrupt* volatile Cyg_Interrupt::dsr_list[CYGNUM_KERNEL_CPU_MAX];
|
Cyg_Interrupt* volatile Cyg_Interrupt::dsr_list[CYGNUM_KERNEL_CPU_MAX];
|
|
|
#endif
|
#endif
|
|
|
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
// Call any pending DSRs
|
// Call any pending DSRs
|
|
|
void
|
void
|
Cyg_Interrupt::call_pending_DSRs_inner(void)
|
Cyg_Interrupt::call_pending_DSRs_inner(void)
|
{
|
{
|
// CYG_REPORT_FUNCTION();
|
// CYG_REPORT_FUNCTION();
|
|
|
HAL_SMP_CPU_TYPE cpu = CYG_KERNEL_CPU_THIS();
|
HAL_SMP_CPU_TYPE cpu = CYG_KERNEL_CPU_THIS();
|
|
|
#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_TABLE
|
#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_TABLE
|
|
|
while( dsr_table_head[cpu] != dsr_table_tail[cpu] )
|
while( dsr_table_head[cpu] != dsr_table_tail[cpu] )
|
{
|
{
|
Cyg_Interrupt *intr = dsr_table[cpu][dsr_table_head[cpu]];
|
Cyg_Interrupt *intr = dsr_table[cpu][dsr_table_head[cpu]];
|
|
|
dsr_table_head[cpu]++;
|
dsr_table_head[cpu]++;
|
if( dsr_table_head[cpu] >= CYGNUM_KERNEL_INTERRUPTS_DSRS_TABLE_SIZE )
|
if( dsr_table_head[cpu] >= CYGNUM_KERNEL_INTERRUPTS_DSRS_TABLE_SIZE )
|
dsr_table_head[cpu] = 0;
|
dsr_table_head[cpu] = 0;
|
|
|
CYG_INSTRUMENT_INTR(CALL_DSR, intr->vector, 0);
|
CYG_INSTRUMENT_INTR(CALL_DSR, intr->vector, 0);
|
|
|
CYG_ASSERT( intr->dsr != NULL , "No DSR defined");
|
CYG_ASSERT( intr->dsr != NULL , "No DSR defined");
|
|
|
intr->dsr( intr->vector, 1, (CYG_ADDRWORD)intr->data );
|
intr->dsr( intr->vector, 1, (CYG_ADDRWORD)intr->data );
|
}
|
}
|
|
|
#endif
|
#endif
|
|
|
#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST
|
#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST
|
|
|
while( dsr_list[cpu] != NULL )
|
while( dsr_list[cpu] != NULL )
|
{
|
{
|
Cyg_Interrupt* intr;
|
Cyg_Interrupt* intr;
|
cyg_uint32 old_intr;
|
cyg_uint32 old_intr;
|
cyg_count32 count;
|
cyg_count32 count;
|
|
|
HAL_DISABLE_INTERRUPTS(old_intr);
|
HAL_DISABLE_INTERRUPTS(old_intr);
|
|
|
intr = dsr_list[cpu];
|
intr = dsr_list[cpu];
|
dsr_list[cpu] = intr->next_dsr;
|
dsr_list[cpu] = intr->next_dsr;
|
count = intr->dsr_count;
|
count = intr->dsr_count;
|
intr->dsr_count = 0;
|
intr->dsr_count = 0;
|
|
|
HAL_RESTORE_INTERRUPTS(old_intr);
|
HAL_RESTORE_INTERRUPTS(old_intr);
|
|
|
CYG_ASSERT( intr->dsr != NULL , "No DSR defined");
|
CYG_ASSERT( intr->dsr != NULL , "No DSR defined");
|
|
|
intr->dsr( intr->vector, count, (CYG_ADDRWORD)intr->data );
|
intr->dsr( intr->vector, count, (CYG_ADDRWORD)intr->data );
|
|
|
}
|
}
|
|
|
#endif
|
#endif
|
|
|
};
|
};
|
|
|
externC void
|
externC void
|
cyg_interrupt_call_pending_DSRs(void)
|
cyg_interrupt_call_pending_DSRs(void)
|
{
|
{
|
Cyg_Interrupt::call_pending_DSRs_inner();
|
Cyg_Interrupt::call_pending_DSRs_inner();
|
}
|
}
|
|
|
//
|
//
|
// Use HAL supported function to run through the DSRs, but executing using
|
// Use HAL supported function to run through the DSRs, but executing using
|
// the separate interrupt stack if available. This function calls back
|
// the separate interrupt stack if available. This function calls back
|
// into this module via 'cyg_interrupt_call_pending_DSRs' above, to keep
|
// into this module via 'cyg_interrupt_call_pending_DSRs' above, to keep
|
// the whole process as general as possible.
|
// the whole process as general as possible.
|
|
|
void
|
void
|
Cyg_Interrupt::call_pending_DSRs(void)
|
Cyg_Interrupt::call_pending_DSRs(void)
|
{
|
{
|
CYG_ASSERT( Cyg_Scheduler::get_sched_lock() == 1,
|
CYG_ASSERT( Cyg_Scheduler::get_sched_lock() == 1,
|
"DSRs being called with sched_lock not equal to 1");
|
"DSRs being called with sched_lock not equal to 1");
|
HAL_INTERRUPT_STACK_CALL_PENDING_DSRS();
|
HAL_INTERRUPT_STACK_CALL_PENDING_DSRS();
|
}
|
}
|
|
|
|
|
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
|
|
void
|
void
|
Cyg_Interrupt::post_dsr(void)
|
Cyg_Interrupt::post_dsr(void)
|
{
|
{
|
// CYG_REPORT_FUNCTION();
|
// CYG_REPORT_FUNCTION();
|
HAL_SMP_CPU_TYPE cpu = CYG_KERNEL_CPU_THIS();
|
HAL_SMP_CPU_TYPE cpu = CYG_KERNEL_CPU_THIS();
|
|
|
CYG_INSTRUMENT_INTR(POST_DSR, vector, 0);
|
CYG_INSTRUMENT_INTR(POST_DSR, vector, 0);
|
|
|
cyg_uint32 old_intr;
|
cyg_uint32 old_intr;
|
|
|
// We need to disable interrupts during this part to
|
// We need to disable interrupts during this part to
|
// guard against nested interrupts.
|
// guard against nested interrupts.
|
|
|
HAL_DISABLE_INTERRUPTS(old_intr);
|
HAL_DISABLE_INTERRUPTS(old_intr);
|
|
|
#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_TABLE
|
#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_TABLE
|
|
|
dsr_table[cpu][dsr_table_tail[cpu]++] = this;
|
dsr_table[cpu][dsr_table_tail[cpu]++] = this;
|
if( dsr_table_tail[cpu] >= CYGNUM_KERNEL_INTERRUPTS_DSRS_TABLE_SIZE )
|
if( dsr_table_tail[cpu] >= CYGNUM_KERNEL_INTERRUPTS_DSRS_TABLE_SIZE )
|
dsr_table_tail[cpu] = 0;
|
dsr_table_tail[cpu] = 0;
|
|
|
#endif
|
#endif
|
|
|
#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST
|
#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST
|
|
|
// Only add the interrupt to the dsr list if this is
|
// Only add the interrupt to the dsr list if this is
|
// the first DSR call.
|
// the first DSR call.
|
// At present DSRs are pushed onto the list and will be
|
// At present DSRs are pushed onto the list and will be
|
// called in reverse order. We do not define the order
|
// called in reverse order. We do not define the order
|
// in which DSRs are called, so this is acceptable.
|
// in which DSRs are called, so this is acceptable.
|
|
|
if( dsr_count++ == 0 )
|
if( dsr_count++ == 0 )
|
{
|
{
|
next_dsr = dsr_list[cpu];
|
next_dsr = dsr_list[cpu];
|
dsr_list[cpu] = this;
|
dsr_list[cpu] = this;
|
}
|
}
|
|
|
#endif
|
#endif
|
|
|
HAL_RESTORE_INTERRUPTS(old_intr);
|
HAL_RESTORE_INTERRUPTS(old_intr);
|
};
|
};
|
|
|
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
// A C callable interface to Cyg_Interrupt::post_dsr() that can be used from
|
// A C callable interface to Cyg_Interrupt::post_dsr() that can be used from
|
// the HAL.
|
// the HAL.
|
|
|
externC void
|
externC void
|
cyg_interrupt_post_dsr( CYG_ADDRWORD intr_obj )
|
cyg_interrupt_post_dsr( CYG_ADDRWORD intr_obj )
|
{
|
{
|
Cyg_Interrupt* intr = (Cyg_Interrupt*) intr_obj;
|
Cyg_Interrupt* intr = (Cyg_Interrupt*) intr_obj;
|
intr->post_dsr ();
|
intr->post_dsr ();
|
}
|
}
|
|
|
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
|
|
// FIXME: should have better name - Jifl
|
// FIXME: should have better name - Jifl
|
externC void
|
externC void
|
interrupt_end(
|
interrupt_end(
|
cyg_uint32 isr_ret,
|
cyg_uint32 isr_ret,
|
Cyg_Interrupt *intr,
|
Cyg_Interrupt *intr,
|
HAL_SavedRegisters *regs
|
HAL_SavedRegisters *regs
|
)
|
)
|
{
|
{
|
// CYG_REPORT_FUNCTION();
|
// CYG_REPORT_FUNCTION();
|
|
|
#ifdef CYGPKG_KERNEL_SMP_SUPPORT
|
#ifdef CYGPKG_KERNEL_SMP_SUPPORT
|
Cyg_Scheduler::lock();
|
Cyg_Scheduler::lock();
|
#endif
|
#endif
|
|
|
// Sometimes we have a NULL intr object pointer.
|
// Sometimes we have a NULL intr object pointer.
|
cyg_vector vector = (intr!=NULL)?intr->vector:0;
|
cyg_vector vector = (intr!=NULL)?intr->vector:0;
|
|
|
CYG_INSTRUMENT_INTR(END, vector, isr_ret);
|
CYG_INSTRUMENT_INTR(END, vector, isr_ret);
|
|
|
CYG_UNUSED_PARAM( cyg_vector, vector ); // prevent compiler warning
|
CYG_UNUSED_PARAM( cyg_vector, vector ); // prevent compiler warning
|
|
|
#ifndef CYGIMP_KERNEL_INTERRUPTS_CHAIN
|
#ifndef CYGIMP_KERNEL_INTERRUPTS_CHAIN
|
|
|
// Only do this if we are in a non-chained configuration.
|
// Only do this if we are in a non-chained configuration.
|
// If we are chained, then chain_isr below will do the DSR
|
// If we are chained, then chain_isr below will do the DSR
|
// posting.
|
// posting.
|
|
|
if( isr_ret & Cyg_Interrupt::CALL_DSR && intr != NULL ) intr->post_dsr();
|
if( isr_ret & Cyg_Interrupt::CALL_DSR && intr != NULL ) intr->post_dsr();
|
|
|
#endif
|
#endif
|
|
|
#ifdef CYGDBG_KERNEL_DEBUG_GDB_THREAD_SUPPORT
|
#ifdef CYGDBG_KERNEL_DEBUG_GDB_THREAD_SUPPORT
|
|
|
// If we have GDB support enabled, and there is the possibility
|
// If we have GDB support enabled, and there is the possibility
|
// that this thread will be context switched as a result of this
|
// that this thread will be context switched as a result of this
|
// interrupt, then save the pointer to the saved thread context in
|
// interrupt, then save the pointer to the saved thread context in
|
// the thread object so that GDB can get a meaningful context to
|
// the thread object so that GDB can get a meaningful context to
|
// look at.
|
// look at.
|
|
|
Cyg_Scheduler::get_current_thread()->set_saved_context(regs);
|
Cyg_Scheduler::get_current_thread()->set_saved_context(regs);
|
|
|
#endif
|
#endif
|
|
|
// Now unlock the scheduler, which may also call DSRs
|
// Now unlock the scheduler, which may also call DSRs
|
// and cause a thread switch to happen.
|
// and cause a thread switch to happen.
|
|
|
Cyg_Scheduler::unlock();
|
Cyg_Scheduler::unlock();
|
|
|
#ifdef CYGDBG_KERNEL_DEBUG_GDB_THREAD_SUPPORT
|
#ifdef CYGDBG_KERNEL_DEBUG_GDB_THREAD_SUPPORT
|
|
|
Cyg_Scheduler::get_current_thread()->set_saved_context(0);
|
Cyg_Scheduler::get_current_thread()->set_saved_context(0);
|
|
|
#endif
|
#endif
|
|
|
CYG_INSTRUMENT_INTR(RESTORE, vector, 0);
|
CYG_INSTRUMENT_INTR(RESTORE, vector, 0);
|
}
|
}
|
|
|
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
// Interrupt chaining statics.
|
// Interrupt chaining statics.
|
|
|
#ifdef CYGIMP_KERNEL_INTERRUPTS_CHAIN
|
#ifdef CYGIMP_KERNEL_INTERRUPTS_CHAIN
|
|
|
Cyg_Interrupt *Cyg_Interrupt::chain_list[CYGNUM_HAL_ISR_TABLE_SIZE];
|
Cyg_Interrupt *Cyg_Interrupt::chain_list[CYGNUM_HAL_ISR_TABLE_SIZE];
|
|
|
#endif
|
#endif
|
|
|
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
// Chaining ISR inserted in HAL vector
|
// Chaining ISR inserted in HAL vector
|
|
|
#ifdef CYGIMP_KERNEL_INTERRUPTS_CHAIN
|
#ifdef CYGIMP_KERNEL_INTERRUPTS_CHAIN
|
|
|
cyg_uint32
|
cyg_uint32
|
Cyg_Interrupt::chain_isr(cyg_vector vector, CYG_ADDRWORD data)
|
Cyg_Interrupt::chain_isr(cyg_vector vector, CYG_ADDRWORD data)
|
{
|
{
|
Cyg_Interrupt *p = *(Cyg_Interrupt **)data;
|
Cyg_Interrupt *p = *(Cyg_Interrupt **)data;
|
register cyg_uint32 isr_ret = 0;
|
register cyg_uint32 isr_ret = 0;
|
register cyg_uint32 isr_chain_ret = 0;
|
register cyg_uint32 isr_chain_ret = 0;
|
|
|
CYG_INSTRUMENT_INTR(CHAIN_ISR, vector, 0);
|
CYG_INSTRUMENT_INTR(CHAIN_ISR, vector, 0);
|
|
|
while( p != NULL )
|
while( p != NULL )
|
{
|
{
|
if( p->vector == vector )
|
if( p->vector == vector )
|
{
|
{
|
isr_ret = p->isr(vector, p->data);
|
isr_ret = p->isr(vector, p->data);
|
|
|
isr_chain_ret |= isr_ret;
|
isr_chain_ret |= isr_ret;
|
|
|
if( isr_ret & Cyg_Interrupt::CALL_DSR ) p->post_dsr();
|
if( isr_ret & Cyg_Interrupt::CALL_DSR ) p->post_dsr();
|
|
|
if( isr_ret & Cyg_Interrupt::HANDLED ) break;
|
if( isr_ret & Cyg_Interrupt::HANDLED ) break;
|
}
|
}
|
|
|
p = p->next;
|
p = p->next;
|
}
|
}
|
|
|
#ifdef HAL_DEFAULT_ISR
|
#ifdef HAL_DEFAULT_ISR
|
if( (isr_chain_ret & (Cyg_Interrupt::HANDLED|Cyg_Interrupt::CALL_DSR)) == 0 )
|
if( (isr_chain_ret & (Cyg_Interrupt::HANDLED|Cyg_Interrupt::CALL_DSR)) == 0 )
|
{
|
{
|
// If we finished the loop for some reason other than that an
|
// If we finished the loop for some reason other than that an
|
// ISR has handled the interrupt, call any default ISR to either
|
// ISR has handled the interrupt, call any default ISR to either
|
// report the spurious interrupt, or do some other HAL level processing
|
// report the spurious interrupt, or do some other HAL level processing
|
// such as GDB interrupt detection etc.
|
// such as GDB interrupt detection etc.
|
|
|
HAL_DEFAULT_ISR( vector, 0 );
|
HAL_DEFAULT_ISR( vector, 0 );
|
}
|
}
|
#endif
|
#endif
|
|
|
return isr_ret & ~Cyg_Interrupt::CALL_DSR;
|
return isr_ret & ~Cyg_Interrupt::CALL_DSR;
|
}
|
}
|
|
|
#endif
|
#endif
|
|
|
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
// Attach an ISR to an interrupt vector.
|
// Attach an ISR to an interrupt vector.
|
|
|
void
|
void
|
Cyg_Interrupt::attach(void)
|
Cyg_Interrupt::attach(void)
|
{
|
{
|
CYG_REPORT_FUNCTION();
|
CYG_REPORT_FUNCTION();
|
|
|
CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
|
CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
|
CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
|
CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
|
|
|
CYG_INSTRUMENT_INTR(ATTACH, vector, 0);
|
CYG_INSTRUMENT_INTR(ATTACH, vector, 0);
|
|
|
HAL_INTERRUPT_SET_LEVEL( vector, priority );
|
HAL_INTERRUPT_SET_LEVEL( vector, priority );
|
|
|
#ifdef CYGIMP_KERNEL_INTERRUPTS_CHAIN
|
#ifdef CYGIMP_KERNEL_INTERRUPTS_CHAIN
|
|
|
CYG_ASSERT( next == NULL , "Cyg_Interrupt already on a list");
|
CYG_ASSERT( next == NULL , "Cyg_Interrupt already on a list");
|
|
|
cyg_uint32 index;
|
cyg_uint32 index;
|
|
|
HAL_TRANSLATE_VECTOR( vector, index );
|
HAL_TRANSLATE_VECTOR( vector, index );
|
|
|
if( chain_list[index] == NULL )
|
if( chain_list[index] == NULL )
|
{
|
{
|
int in_use;
|
int in_use;
|
// First Interrupt on this chain, just assign it and register
|
// First Interrupt on this chain, just assign it and register
|
// the chain_isr with the HAL.
|
// the chain_isr with the HAL.
|
|
|
chain_list[index] = this;
|
chain_list[index] = this;
|
|
|
HAL_INTERRUPT_IN_USE( vector, in_use );
|
HAL_INTERRUPT_IN_USE( vector, in_use );
|
CYG_ASSERT( 0 == in_use, "Interrupt vector not free.");
|
CYG_ASSERT( 0 == in_use, "Interrupt vector not free.");
|
HAL_INTERRUPT_ATTACH( vector, chain_isr, &chain_list[index], NULL );
|
HAL_INTERRUPT_ATTACH( vector, chain_isr, &chain_list[index], NULL );
|
}
|
}
|
else
|
else
|
{
|
{
|
// There are already interrupts chained, add this one into the
|
// There are already interrupts chained, add this one into the
|
// chain in priority order.
|
// chain in priority order.
|
|
|
Cyg_Interrupt **p = &chain_list[index];
|
Cyg_Interrupt **p = &chain_list[index];
|
|
|
while( *p != NULL )
|
while( *p != NULL )
|
{
|
{
|
Cyg_Interrupt *n = *p;
|
Cyg_Interrupt *n = *p;
|
|
|
if( n->priority < priority ) break;
|
if( n->priority < priority ) break;
|
|
|
p = &n->next;
|
p = &n->next;
|
}
|
}
|
next = *p;
|
next = *p;
|
*p = this;
|
*p = this;
|
}
|
}
|
|
|
#else
|
#else
|
|
|
{
|
{
|
int in_use;
|
int in_use;
|
|
|
|
|
HAL_INTERRUPT_IN_USE( vector, in_use );
|
HAL_INTERRUPT_IN_USE( vector, in_use );
|
CYG_ASSERT( 0 == in_use, "Interrupt vector not free.");
|
CYG_ASSERT( 0 == in_use, "Interrupt vector not free.");
|
|
|
HAL_INTERRUPT_ATTACH( vector, isr, data, this );
|
HAL_INTERRUPT_ATTACH( vector, isr, data, this );
|
}
|
}
|
|
|
#endif
|
#endif
|
CYG_REPORT_RETURN();
|
CYG_REPORT_RETURN();
|
}
|
}
|
|
|
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
// Detach the ISR from the vector
|
// Detach the ISR from the vector
|
|
|
void
|
void
|
Cyg_Interrupt::detach(void)
|
Cyg_Interrupt::detach(void)
|
{
|
{
|
CYG_REPORT_FUNCTION();
|
CYG_REPORT_FUNCTION();
|
|
|
CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
|
CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
|
CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
|
CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
|
|
|
CYG_INSTRUMENT_INTR(DETACH, vector, 0);
|
CYG_INSTRUMENT_INTR(DETACH, vector, 0);
|
|
|
#ifdef CYGIMP_KERNEL_INTERRUPTS_CHAIN
|
#ifdef CYGIMP_KERNEL_INTERRUPTS_CHAIN
|
|
|
// Remove the interrupt object from the vector chain.
|
// Remove the interrupt object from the vector chain.
|
|
|
cyg_uint32 index;
|
cyg_uint32 index;
|
|
|
HAL_TRANSLATE_VECTOR( vector, index );
|
HAL_TRANSLATE_VECTOR( vector, index );
|
|
|
Cyg_Interrupt **p = &chain_list[index];
|
Cyg_Interrupt **p = &chain_list[index];
|
|
|
while( *p != NULL )
|
while( *p != NULL )
|
{
|
{
|
Cyg_Interrupt *n = *p;
|
Cyg_Interrupt *n = *p;
|
|
|
if( n == this )
|
if( n == this )
|
{
|
{
|
*p = next;
|
*p = next;
|
break;
|
break;
|
}
|
}
|
|
|
p = &n->next;
|
p = &n->next;
|
}
|
}
|
|
|
// If this was the last one, detach the vector.
|
// If this was the last one, detach the vector.
|
|
|
if( chain_list[index] == NULL )
|
if( chain_list[index] == NULL )
|
HAL_INTERRUPT_DETACH( vector, chain_isr );
|
HAL_INTERRUPT_DETACH( vector, chain_isr );
|
|
|
#else
|
#else
|
|
|
HAL_INTERRUPT_DETACH( vector, isr );
|
HAL_INTERRUPT_DETACH( vector, isr );
|
|
|
#endif
|
#endif
|
|
|
CYG_REPORT_RETURN();
|
CYG_REPORT_RETURN();
|
|
|
}
|
}
|
|
|
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
// Get the current service routine
|
// Get the current service routine
|
|
|
void
|
void
|
Cyg_Interrupt::get_vsr(cyg_vector vector, cyg_VSR **vsr)
|
Cyg_Interrupt::get_vsr(cyg_vector vector, cyg_VSR **vsr)
|
{
|
{
|
CYG_REPORT_FUNCTION();
|
CYG_REPORT_FUNCTION();
|
CYG_REPORT_FUNCARG2("vector = %d, mem to put VSR in is at %08x", vector,
|
CYG_REPORT_FUNCARG2("vector = %d, mem to put VSR in is at %08x", vector,
|
vsr);
|
vsr);
|
|
|
CYG_ASSERT( vector >= CYGNUM_HAL_VSR_MIN, "Invalid vector");
|
CYG_ASSERT( vector >= CYGNUM_HAL_VSR_MIN, "Invalid vector");
|
CYG_ASSERT( vector <= CYGNUM_HAL_VSR_MAX, "Invalid vector");
|
CYG_ASSERT( vector <= CYGNUM_HAL_VSR_MAX, "Invalid vector");
|
|
|
HAL_VSR_GET( vector, vsr );
|
HAL_VSR_GET( vector, vsr );
|
|
|
CYG_REPORT_RETURN();
|
CYG_REPORT_RETURN();
|
}
|
}
|
|
|
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
// Install a vector service routine
|
// Install a vector service routine
|
|
|
void
|
void
|
Cyg_Interrupt::set_vsr(cyg_vector vector, cyg_VSR *vsr, cyg_VSR **old)
|
Cyg_Interrupt::set_vsr(cyg_vector vector, cyg_VSR *vsr, cyg_VSR **old)
|
{
|
{
|
CYG_REPORT_FUNCTION();
|
CYG_REPORT_FUNCTION();
|
|
|
CYG_REPORT_FUNCARG3( "vector = %d, new vsr is at %08x, mem to put "
|
CYG_REPORT_FUNCARG3( "vector = %d, new vsr is at %08x, mem to put "
|
"old VSR in is at %08x", vector, vsr, old);
|
"old VSR in is at %08x", vector, vsr, old);
|
|
|
CYG_INSTRUMENT_INTR(SET_VSR, vector, vsr);
|
CYG_INSTRUMENT_INTR(SET_VSR, vector, vsr);
|
|
|
CYG_ASSERT( vector >= CYGNUM_HAL_VSR_MIN, "Invalid vector");
|
CYG_ASSERT( vector >= CYGNUM_HAL_VSR_MIN, "Invalid vector");
|
CYG_ASSERT( vector <= CYGNUM_HAL_VSR_MAX, "Invalid vector");
|
CYG_ASSERT( vector <= CYGNUM_HAL_VSR_MAX, "Invalid vector");
|
|
|
CYG_INTERRUPT_STATE old_ints;
|
CYG_INTERRUPT_STATE old_ints;
|
|
|
HAL_DISABLE_INTERRUPTS(old_ints);
|
HAL_DISABLE_INTERRUPTS(old_ints);
|
|
|
HAL_VSR_SET( vector, vsr, old );
|
HAL_VSR_SET( vector, vsr, old );
|
|
|
HAL_RESTORE_INTERRUPTS(old_ints);
|
HAL_RESTORE_INTERRUPTS(old_ints);
|
|
|
CYG_REPORT_RETURN();
|
CYG_REPORT_RETURN();
|
}
|
}
|
|
|
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
// Disable interrupts at the CPU
|
// Disable interrupts at the CPU
|
|
|
|
|
void
|
void
|
Cyg_Interrupt::disable_interrupts(void)
|
Cyg_Interrupt::disable_interrupts(void)
|
{
|
{
|
CYG_REPORT_FUNCTION();
|
CYG_REPORT_FUNCTION();
|
|
|
CYG_INSTRUMENT_INTR(DISABLE, disable_counter[CYG_KERNEL_CPU_THIS()]+1, 0);
|
CYG_INSTRUMENT_INTR(DISABLE, disable_counter[CYG_KERNEL_CPU_THIS()]+1, 0);
|
|
|
HAL_SMP_CPU_TYPE cpu_this = CYG_KERNEL_CPU_THIS();
|
HAL_SMP_CPU_TYPE cpu_this = CYG_KERNEL_CPU_THIS();
|
|
|
// If the disable_counter is zero, disable interrupts and claim the spinlock.
|
// If the disable_counter is zero, disable interrupts and claim the spinlock.
|
|
|
if( 0 == disable_counter[cpu_this] )
|
if( 0 == disable_counter[cpu_this] )
|
{
|
{
|
// Claim the spinlock and disable interrupts. We save the original interrupt
|
// Claim the spinlock and disable interrupts. We save the original interrupt
|
// enable state to restore later.
|
// enable state to restore later.
|
interrupt_disable_spinlock.spin_intsave(&interrupt_disable_state[cpu_this]);
|
interrupt_disable_spinlock.spin_intsave(&interrupt_disable_state[cpu_this]);
|
}
|
}
|
|
|
// Now increment our disable counter.
|
// Now increment our disable counter.
|
|
|
disable_counter[cpu_this]++;
|
disable_counter[cpu_this]++;
|
|
|
CYG_REPORT_RETURN();
|
CYG_REPORT_RETURN();
|
}
|
}
|
|
|
|
|
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
// Re-enable CPU interrupts
|
// Re-enable CPU interrupts
|
|
|
void
|
void
|
Cyg_Interrupt::enable_interrupts(void)
|
Cyg_Interrupt::enable_interrupts(void)
|
{
|
{
|
CYG_REPORT_FUNCTION();
|
CYG_REPORT_FUNCTION();
|
|
|
CYG_INSTRUMENT_INTR(ENABLE, disable_counter[CYG_KERNEL_CPU_THIS()], 0);
|
CYG_INSTRUMENT_INTR(ENABLE, disable_counter[CYG_KERNEL_CPU_THIS()], 0);
|
|
|
HAL_SMP_CPU_TYPE cpu_this = CYG_KERNEL_CPU_THIS();
|
HAL_SMP_CPU_TYPE cpu_this = CYG_KERNEL_CPU_THIS();
|
|
|
CYG_ASSERT( disable_counter[cpu_this] > 0 , "Disable counter not greater than zero");
|
CYG_ASSERT( disable_counter[cpu_this] > 0 , "Disable counter not greater than zero");
|
|
|
// If the disable counter goes to zero, then release the spinlock and restore
|
// If the disable counter goes to zero, then release the spinlock and restore
|
// the previous interrupt state.
|
// the previous interrupt state.
|
|
|
if( --disable_counter[cpu_this] == 0 )
|
if( --disable_counter[cpu_this] == 0 )
|
{
|
{
|
interrupt_disable_spinlock.clear_intsave(interrupt_disable_state[cpu_this]);
|
interrupt_disable_spinlock.clear_intsave(interrupt_disable_state[cpu_this]);
|
}
|
}
|
|
|
CYG_REPORT_RETURN();
|
CYG_REPORT_RETURN();
|
}
|
}
|
|
|
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
// Mask a specific interrupt in a PIC
|
// Mask a specific interrupt in a PIC
|
|
|
void
|
void
|
Cyg_Interrupt::mask_interrupt(cyg_vector vector)
|
Cyg_Interrupt::mask_interrupt(cyg_vector vector)
|
{
|
{
|
CYG_REPORT_FUNCTION();
|
CYG_REPORT_FUNCTION();
|
CYG_REPORT_FUNCARG1("vector=%d", vector);
|
CYG_REPORT_FUNCARG1("vector=%d", vector);
|
|
|
CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
|
CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
|
CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
|
CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
|
|
|
CYG_INSTRUMENT_INTR(MASK, vector, 0);
|
CYG_INSTRUMENT_INTR(MASK, vector, 0);
|
|
|
CYG_INTERRUPT_STATE old_ints;
|
CYG_INTERRUPT_STATE old_ints;
|
|
|
HAL_DISABLE_INTERRUPTS(old_ints);
|
HAL_DISABLE_INTERRUPTS(old_ints);
|
HAL_INTERRUPT_MASK( vector );
|
HAL_INTERRUPT_MASK( vector );
|
HAL_RESTORE_INTERRUPTS(old_ints);
|
HAL_RESTORE_INTERRUPTS(old_ints);
|
|
|
CYG_REPORT_RETURN();
|
CYG_REPORT_RETURN();
|
}
|
}
|
|
|
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
// Mask a specific interrupt in a PIC (but not interrupt safe)
|
// Mask a specific interrupt in a PIC (but not interrupt safe)
|
|
|
void
|
void
|
Cyg_Interrupt::mask_interrupt_intunsafe(cyg_vector vector)
|
Cyg_Interrupt::mask_interrupt_intunsafe(cyg_vector vector)
|
{
|
{
|
CYG_REPORT_FUNCTION();
|
CYG_REPORT_FUNCTION();
|
CYG_REPORT_FUNCARG1("vector=%d", vector);
|
CYG_REPORT_FUNCARG1("vector=%d", vector);
|
|
|
|
|
CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
|
CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
|
CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
|
CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
|
|
|
CYG_INSTRUMENT_INTR(MASK, vector, 0);
|
CYG_INSTRUMENT_INTR(MASK, vector, 0);
|
|
|
HAL_INTERRUPT_MASK( vector );
|
HAL_INTERRUPT_MASK( vector );
|
|
|
CYG_REPORT_RETURN();
|
CYG_REPORT_RETURN();
|
}
|
}
|
|
|
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
// Clear PIC mask
|
// Clear PIC mask
|
|
|
void
|
void
|
Cyg_Interrupt::unmask_interrupt(cyg_vector vector)
|
Cyg_Interrupt::unmask_interrupt(cyg_vector vector)
|
{
|
{
|
CYG_REPORT_FUNCTION();
|
CYG_REPORT_FUNCTION();
|
|
|
CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
|
CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
|
CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
|
CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
|
|
|
CYG_INSTRUMENT_INTR(UNMASK, vector, 0);
|
CYG_INSTRUMENT_INTR(UNMASK, vector, 0);
|
|
|
CYG_INTERRUPT_STATE old_ints;
|
CYG_INTERRUPT_STATE old_ints;
|
|
|
HAL_DISABLE_INTERRUPTS(old_ints);
|
HAL_DISABLE_INTERRUPTS(old_ints);
|
HAL_INTERRUPT_UNMASK( vector );
|
HAL_INTERRUPT_UNMASK( vector );
|
HAL_RESTORE_INTERRUPTS(old_ints);
|
HAL_RESTORE_INTERRUPTS(old_ints);
|
|
|
CYG_REPORT_RETURN();
|
CYG_REPORT_RETURN();
|
}
|
}
|
|
|
|
|
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
// Clear PIC mask (but not interrupt safe)
|
// Clear PIC mask (but not interrupt safe)
|
|
|
void
|
void
|
Cyg_Interrupt::unmask_interrupt_intunsafe(cyg_vector vector)
|
Cyg_Interrupt::unmask_interrupt_intunsafe(cyg_vector vector)
|
{
|
{
|
CYG_REPORT_FUNCTION();
|
CYG_REPORT_FUNCTION();
|
|
|
CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
|
CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
|
CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
|
CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
|
|
|
CYG_INSTRUMENT_INTR(UNMASK, vector, 0);
|
CYG_INSTRUMENT_INTR(UNMASK, vector, 0);
|
|
|
HAL_INTERRUPT_UNMASK( vector );
|
HAL_INTERRUPT_UNMASK( vector );
|
|
|
CYG_REPORT_RETURN();
|
CYG_REPORT_RETURN();
|
}
|
}
|
|
|
|
|
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
// Acknowledge interrupt at PIC
|
// Acknowledge interrupt at PIC
|
|
|
void
|
void
|
Cyg_Interrupt::acknowledge_interrupt(cyg_vector vector)
|
Cyg_Interrupt::acknowledge_interrupt(cyg_vector vector)
|
{
|
{
|
// CYG_REPORT_FUNCTION();
|
// CYG_REPORT_FUNCTION();
|
|
|
CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
|
CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
|
CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
|
CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
|
|
|
CYG_INSTRUMENT_INTR(ACK, vector, 0);
|
CYG_INSTRUMENT_INTR(ACK, vector, 0);
|
|
|
HAL_INTERRUPT_ACKNOWLEDGE( vector );
|
HAL_INTERRUPT_ACKNOWLEDGE( vector );
|
}
|
}
|
|
|
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
// Change interrupt detection at PIC
|
// Change interrupt detection at PIC
|
|
|
void
|
void
|
Cyg_Interrupt::configure_interrupt(
|
Cyg_Interrupt::configure_interrupt(
|
cyg_vector vector, // vector to control
|
cyg_vector vector, // vector to control
|
cyg_bool level, // level or edge triggered
|
cyg_bool level, // level or edge triggered
|
cyg_bool up // hi/lo level, rising/falling edge
|
cyg_bool up // hi/lo level, rising/falling edge
|
)
|
)
|
{
|
{
|
CYG_REPORT_FUNCTION();
|
CYG_REPORT_FUNCTION();
|
CYG_REPORT_FUNCARG3("vector = %d, level = %d, up = %d", vector, level,
|
CYG_REPORT_FUNCARG3("vector = %d, level = %d, up = %d", vector, level,
|
up);
|
up);
|
|
|
CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
|
CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
|
CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
|
CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
|
|
|
CYG_INSTRUMENT_INTR(CONFIGURE, vector, (level<<1)|up);
|
CYG_INSTRUMENT_INTR(CONFIGURE, vector, (level<<1)|up);
|
|
|
HAL_INTERRUPT_CONFIGURE( vector, level, up );
|
HAL_INTERRUPT_CONFIGURE( vector, level, up );
|
|
|
CYG_REPORT_RETURN();
|
CYG_REPORT_RETURN();
|
}
|
}
|
|
|
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
// SMP support for setting/getting interrupt CPU
|
// SMP support for setting/getting interrupt CPU
|
|
|
#ifdef CYGPKG_KERNEL_SMP_SUPPORT
|
#ifdef CYGPKG_KERNEL_SMP_SUPPORT
|
|
|
void
|
void
|
Cyg_Interrupt::set_cpu(
|
Cyg_Interrupt::set_cpu(
|
cyg_vector vector, // vector to control
|
cyg_vector vector, // vector to control
|
HAL_SMP_CPU_TYPE cpu // CPU to set
|
HAL_SMP_CPU_TYPE cpu // CPU to set
|
)
|
)
|
{
|
{
|
CYG_REPORT_FUNCTION();
|
CYG_REPORT_FUNCTION();
|
CYG_REPORT_FUNCARG2("vector = %d, cpu = %d", vector, cpu );
|
CYG_REPORT_FUNCARG2("vector = %d, cpu = %d", vector, cpu );
|
|
|
CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
|
CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
|
CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
|
CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
|
|
|
CYG_INSTRUMENT_INTR(SET_CPU, vector, cpu);
|
CYG_INSTRUMENT_INTR(SET_CPU, vector, cpu);
|
|
|
HAL_INTERRUPT_SET_CPU( vector, cpu );
|
HAL_INTERRUPT_SET_CPU( vector, cpu );
|
|
|
CYG_REPORT_RETURN();
|
CYG_REPORT_RETURN();
|
}
|
}
|
|
|
HAL_SMP_CPU_TYPE
|
HAL_SMP_CPU_TYPE
|
Cyg_Interrupt::get_cpu(
|
Cyg_Interrupt::get_cpu(
|
cyg_vector vector // vector to control
|
cyg_vector vector // vector to control
|
)
|
)
|
{
|
{
|
CYG_REPORT_FUNCTION();
|
CYG_REPORT_FUNCTION();
|
CYG_REPORT_FUNCARG1("vector = %d", vector);
|
CYG_REPORT_FUNCARG1("vector = %d", vector);
|
|
|
CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
|
CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
|
CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
|
CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
|
|
|
HAL_SMP_CPU_TYPE cpu = 0;
|
HAL_SMP_CPU_TYPE cpu = 0;
|
|
|
HAL_INTERRUPT_GET_CPU( vector, cpu );
|
HAL_INTERRUPT_GET_CPU( vector, cpu );
|
|
|
CYG_INSTRUMENT_INTR(GET_CPU, vector, cpu);
|
CYG_INSTRUMENT_INTR(GET_CPU, vector, cpu);
|
|
|
CYG_REPORT_RETURN();
|
CYG_REPORT_RETURN();
|
|
|
return cpu;
|
return cpu;
|
}
|
}
|
|
|
#endif
|
#endif
|
|
|
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
// EOF intr/intr.cxx
|
// EOF intr/intr.cxx
|
|
|