📄 intr.cxx
字号:
{
CYG_REPORT_FUNCTION();
CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
CYG_INSTRUMENT_INTR(ATTACH, vector, 0);
HAL_INTERRUPT_SET_LEVEL( vector, priority );
#ifdef CYGIMP_KERNEL_INTERRUPTS_CHAIN
CYG_ASSERT( next == NULL , "Cyg_Interrupt already on a list");
cyg_uint32 index;
HAL_TRANSLATE_VECTOR( vector, index );
if( chain_list[index] == NULL )
{
int in_use;
// First Interrupt on this chain, just assign it and register
// the chain_isr with the HAL.
chain_list[index] = this;
HAL_INTERRUPT_IN_USE( vector, in_use );
CYG_ASSERT( 0 == in_use, "Interrupt vector not free.");
HAL_INTERRUPT_ATTACH( vector, chain_isr, &chain_list[index], NULL );
}
else
{
// There are already interrupts chained, add this one into the
// chain in priority order.
Cyg_Interrupt **p = &chain_list[index];
while( *p != NULL )
{
Cyg_Interrupt *n = *p;
if( n->priority < priority ) break;
p = &n->next;
}
next = *p;
*p = this;
}
#else
{
int in_use;
HAL_INTERRUPT_IN_USE( vector, in_use );
CYG_ASSERT( 0 == in_use, "Interrupt vector not free.");
HAL_INTERRUPT_ATTACH( vector, isr, data, this );
}
#endif
CYG_REPORT_RETURN();
}
// -------------------------------------------------------------------------
// Detach the ISR from the vector
void
Cyg_Interrupt::detach(void)
{
CYG_REPORT_FUNCTION();
CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
CYG_INSTRUMENT_INTR(DETACH, vector, 0);
#ifdef CYGIMP_KERNEL_INTERRUPTS_CHAIN
// Remove the interrupt object from the vector chain.
cyg_uint32 index;
HAL_TRANSLATE_VECTOR( vector, index );
Cyg_Interrupt **p = &chain_list[index];
while( *p != NULL )
{
Cyg_Interrupt *n = *p;
if( n == this )
{
*p = next;
break;
}
p = &n->next;
}
// If this was the last one, detach the vector.
if( chain_list[index] == NULL )
HAL_INTERRUPT_DETACH( vector, chain_isr );
#else
HAL_INTERRUPT_DETACH( vector, isr );
#endif
CYG_REPORT_RETURN();
}
// -------------------------------------------------------------------------
// Get the current service routine
void
Cyg_Interrupt::get_vsr(cyg_vector vector, cyg_VSR **vsr)
{
CYG_REPORT_FUNCTION();
CYG_REPORT_FUNCARG2("vector = %d, mem to put VSR in is at %08x", vector,
vsr);
CYG_ASSERT( vector >= CYGNUM_HAL_VSR_MIN, "Invalid vector");
CYG_ASSERT( vector <= CYGNUM_HAL_VSR_MAX, "Invalid vector");
HAL_VSR_GET( vector, vsr );
CYG_REPORT_RETURN();
}
// -------------------------------------------------------------------------
// Install a vector service routine
void
Cyg_Interrupt::set_vsr(cyg_vector vector, cyg_VSR *vsr, cyg_VSR **old)
{
CYG_REPORT_FUNCTION();
CYG_REPORT_FUNCARG3( "vector = %d, new vsr is at %08x, mem to put "
"old VSR in is at %08x", vector, vsr, old);
CYG_INSTRUMENT_INTR(SET_VSR, vector, vsr);
CYG_ASSERT( vector >= CYGNUM_HAL_VSR_MIN, "Invalid vector");
CYG_ASSERT( vector <= CYGNUM_HAL_VSR_MAX, "Invalid vector");
CYG_INTERRUPT_STATE old_ints;
HAL_DISABLE_INTERRUPTS(old_ints);
HAL_VSR_SET( vector, vsr, old );
HAL_RESTORE_INTERRUPTS(old_ints);
CYG_REPORT_RETURN();
}
// -------------------------------------------------------------------------
// Disable interrupts at the CPU
void
Cyg_Interrupt::disable_interrupts(void)
{
CYG_REPORT_FUNCTION();
CYG_INSTRUMENT_INTR(DISABLE, disable_counter[CYG_KERNEL_CPU_THIS()]+1, 0);
HAL_SMP_CPU_TYPE cpu_this = CYG_KERNEL_CPU_THIS();
// If the disable_counter is zero, disable interrupts and claim the spinlock.
if( 0 == disable_counter[cpu_this] )
{
// Claim the spinlock and disable interrupts. We save the original interrupt
// enable state to restore later.
interrupt_disable_spinlock.spin_intsave(&interrupt_disable_state[cpu_this]);
}
// Now increment our disable counter.
disable_counter[cpu_this]++;
CYG_REPORT_RETURN();
}
// -------------------------------------------------------------------------
// Re-enable CPU interrupts
void
Cyg_Interrupt::enable_interrupts(void)
{
CYG_REPORT_FUNCTION();
CYG_INSTRUMENT_INTR(ENABLE, disable_counter[CYG_KERNEL_CPU_THIS()], 0);
HAL_SMP_CPU_TYPE cpu_this = CYG_KERNEL_CPU_THIS();
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
// the previous interrupt state.
if( --disable_counter[cpu_this] == 0 )
{
interrupt_disable_spinlock.clear_intsave(interrupt_disable_state[cpu_this]);
}
CYG_REPORT_RETURN();
}
// -------------------------------------------------------------------------
// Mask a specific interrupt in a PIC
void
Cyg_Interrupt::mask_interrupt(cyg_vector vector)
{
CYG_REPORT_FUNCTION();
CYG_REPORT_FUNCARG1("vector=%d", vector);
CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
CYG_INSTRUMENT_INTR(MASK, vector, 0);
CYG_INTERRUPT_STATE old_ints;
HAL_DISABLE_INTERRUPTS(old_ints);
HAL_INTERRUPT_MASK( vector );
HAL_RESTORE_INTERRUPTS(old_ints);
CYG_REPORT_RETURN();
}
// -------------------------------------------------------------------------
// Mask a specific interrupt in a PIC (but not interrupt safe)
void
Cyg_Interrupt::mask_interrupt_intunsafe(cyg_vector vector)
{
CYG_REPORT_FUNCTION();
CYG_REPORT_FUNCARG1("vector=%d", vector);
CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
CYG_INSTRUMENT_INTR(MASK, vector, 0);
HAL_INTERRUPT_MASK( vector );
CYG_REPORT_RETURN();
}
// -------------------------------------------------------------------------
// Clear PIC mask
void
Cyg_Interrupt::unmask_interrupt(cyg_vector vector)
{
CYG_REPORT_FUNCTION();
CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
CYG_INSTRUMENT_INTR(UNMASK, vector, 0);
CYG_INTERRUPT_STATE old_ints;
HAL_DISABLE_INTERRUPTS(old_ints);
HAL_INTERRUPT_UNMASK( vector );
HAL_RESTORE_INTERRUPTS(old_ints);
CYG_REPORT_RETURN();
}
// -------------------------------------------------------------------------
// Clear PIC mask (but not interrupt safe)
void
Cyg_Interrupt::unmask_interrupt_intunsafe(cyg_vector vector)
{
CYG_REPORT_FUNCTION();
CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
CYG_INSTRUMENT_INTR(UNMASK, vector, 0);
HAL_INTERRUPT_UNMASK( vector );
CYG_REPORT_RETURN();
}
// -------------------------------------------------------------------------
// Acknowledge interrupt at PIC
void
Cyg_Interrupt::acknowledge_interrupt(cyg_vector vector)
{
// CYG_REPORT_FUNCTION();
CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
CYG_INSTRUMENT_INTR(ACK, vector, 0);
HAL_INTERRUPT_ACKNOWLEDGE( vector );
}
// -------------------------------------------------------------------------
// Change interrupt detection at PIC
void
Cyg_Interrupt::configure_interrupt(
cyg_vector vector, // vector to control
cyg_bool level, // level or edge triggered
cyg_bool up // hi/lo level, rising/falling edge
)
{
CYG_REPORT_FUNCTION();
CYG_REPORT_FUNCARG3("vector = %d, level = %d, up = %d", vector, level,
up);
CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
CYG_INSTRUMENT_INTR(CONFIGURE, vector, (level<<1)|up);
HAL_INTERRUPT_CONFIGURE( vector, level, up );
CYG_REPORT_RETURN();
}
// -------------------------------------------------------------------------
// SMP support for setting/getting interrupt CPU
#ifdef CYGPKG_KERNEL_SMP_SUPPORT
void
Cyg_Interrupt::set_cpu(
cyg_vector vector, // vector to control
HAL_SMP_CPU_TYPE cpu // CPU to set
)
{
CYG_REPORT_FUNCTION();
CYG_REPORT_FUNCARG2("vector = %d, cpu = %d", vector, cpu );
CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
CYG_INSTRUMENT_INTR(SET_CPU, vector, cpu);
HAL_INTERRUPT_SET_CPU( vector, cpu );
CYG_REPORT_RETURN();
}
HAL_SMP_CPU_TYPE
Cyg_Interrupt::get_cpu(
cyg_vector vector // vector to control
)
{
CYG_REPORT_FUNCTION();
CYG_REPORT_FUNCARG1("vector = %d", vector);
CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
HAL_SMP_CPU_TYPE cpu = 0;
HAL_INTERRUPT_GET_CPU( vector, cpu );
CYG_INSTRUMENT_INTR(GET_CPU, vector, cpu);
CYG_REPORT_RETURN();
return cpu;
}
#endif
// -------------------------------------------------------------------------
// EOF intr/intr.cxx
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -