Mercurial > ecos
diff packages/kernel/current/src/intr/intr.cxx @ 2:443894e2e912 ecos-v1_2_1-release
Block commit of eCos version 1.2.1
| author | jlarmour |
|---|---|
| date | Tue, 11 May 1999 12:24:34 +0000 |
| parents | 3111d98ba7b3 |
| children | ece80412419a |
line wrap: on
line diff
--- a/packages/kernel/current/src/intr/intr.cxx +++ b/packages/kernel/current/src/intr/intr.cxx @@ -1,8 +1,8 @@ //========================================================================== // -// intr/intr.cxx +// intr/intr.cxx // -// Interrupt class implementations +// Interrupt class implementations // //========================================================================== //####COPYRIGHTBEGIN#### @@ -22,19 +22,19 @@ // September 30, 1998. // // The Initial Developer of the Original Code is Cygnus. Portions created -// by Cygnus are Copyright (C) 1998 Cygnus Solutions. All Rights Reserved. +// by Cygnus are Copyright (C) 1998,1999 Cygnus Solutions. All Rights Reserved. // ------------------------------------------- // //####COPYRIGHTEND#### //========================================================================== //#####DESCRIPTIONBEGIN#### // -// Author(s): nickg -// Contributors: nickg -// Date: 1997-10-15 -// Purpose: Interrupt class implementation -// Description: This file contains the definitions of the interrupt -// class. +// Author(s): nickg +// Contributors: nickg +// Date: 1999-02-17 +// Purpose: Interrupt class implementation +// Description: This file contains the definitions of the interrupt +// class. // //####DESCRIPTIONEND#### // @@ -54,6 +54,14 @@ #include <cyg/kernel/sched.inl> // ------------------------------------------------------------------------- +// Statics + +// Interrupt disable counter. Note that this is initialized to 1 since +// enable_interrupts() is called in Cyg_Scheduler::start(). + +cyg_int32 Cyg_Interrupt::disable_counter = 1; + +// ------------------------------------------------------------------------- Cyg_Interrupt::Cyg_Interrupt( cyg_vector vec, // Vector to attach to @@ -63,6 +71,10 @@ Cyg_Interrupt::Cyg_Interrupt( cyg_DSR *dr // Deferred Service Routine ) { + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG5("vector=%d, priority=%d, data=%08x, isr=%08x, " + "dsr=%08x", vec, pri, d, ir, dr); + vector = vec; priority = pri; isr = ir; @@ -81,6 +93,8 @@ Cyg_Interrupt::Cyg_Interrupt( next = NULL; #endif + + CYG_REPORT_RETURN(); }; @@ -88,7 +102,9 @@ Cyg_Interrupt::Cyg_Interrupt( Cyg_Interrupt::~Cyg_Interrupt() { + CYG_REPORT_FUNCTION(); detach(); + CYG_REPORT_RETURN(); }; // ------------------------------------------------------------------------- @@ -96,7 +112,8 @@ Cyg_Interrupt::~Cyg_Interrupt() #ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_TABLE -Cyg_Interrupt *Cyg_Interrupt::dsr_table[CYGNUM_KERNEL_INTERRUPTS_DSRS_TABLE_SIZE]; +Cyg_Interrupt * +Cyg_Interrupt::dsr_table[CYGNUM_KERNEL_INTERRUPTS_DSRS_TABLE_SIZE]; cyg_ucount32 Cyg_Interrupt::dsr_table_head = 0; @@ -113,7 +130,8 @@ Cyg_Interrupt *Cyg_Interrupt::dsr_list = // ------------------------------------------------------------------------- // Call any pending DSRs -void Cyg_Interrupt::call_pending_DSRs() +void +Cyg_Interrupt::call_pending_DSRs_inner(void) { // CYG_REPORT_FUNCTION(); @@ -159,9 +177,29 @@ void Cyg_Interrupt::call_pending_DSRs() }; +externC void +cyg_interrupt_call_pending_DSRs(void) +{ + Cyg_Interrupt::call_pending_DSRs_inner(); +} + +// This function will be provided by HALs that fully implement +// interrupt stack functionality +externC void +hal_interrupt_stack_call_pending_DSRs(void) + __attribute__ ((weak, alias("cyg_interrupt_call_pending_DSRs"))); + +void +Cyg_Interrupt::call_pending_DSRs(void) +{ + hal_interrupt_stack_call_pending_DSRs(); +} + + // ------------------------------------------------------------------------- -void Cyg_Interrupt::post_dsr() +void +Cyg_Interrupt::post_dsr(void) { // CYG_REPORT_FUNCTION(); @@ -202,8 +240,21 @@ void Cyg_Interrupt::post_dsr() }; // ------------------------------------------------------------------------- +// A C callable interface to Cyg_Interrupt::post_dsr() that can be used from +// the HAL. -externC void interrupt_end( +externC void +cyg_interrupt_post_dsr( CYG_ADDRWORD intr_obj ) +{ + Cyg_Interrupt* intr = (Cyg_Interrupt*) intr_obj; + intr->post_dsr (); +} + +// ------------------------------------------------------------------------- + +// FIXME: should have better name - Jifl +externC void +interrupt_end( cyg_uint32 isr_ret, Cyg_Interrupt *intr, HAL_SavedRegisters *regs @@ -211,15 +262,19 @@ externC void interrupt_end( { // CYG_REPORT_FUNCTION(); - CYG_INSTRUMENT_INTR(END, intr->vector, isr_ret); - + // Sometimes we have a NULL intr object pointer. + cyg_vector vector = (intr!=NULL)?intr->vector:0; + + CYG_INSTRUMENT_INTR(END, vector, isr_ret); + + #ifndef CYGIMP_KERNEL_INTERRUPTS_CHAIN // Only do this if we are in a non-chained configuration. // If we are chained, then chain_isr below will do the DSR // posting. - if( isr_ret & 2 ) intr->post_dsr(); + if( isr_ret & Cyg_Interrupt::CALL_DSR && intr != NULL ) intr->post_dsr(); #endif @@ -246,8 +301,7 @@ externC void interrupt_end( #endif - - CYG_INSTRUMENT_INTR(RESTORE, intr->vector, 0); + CYG_INSTRUMENT_INTR(RESTORE, vector, 0); } // ------------------------------------------------------------------------- @@ -255,7 +309,7 @@ externC void interrupt_end( #ifdef CYGIMP_KERNEL_INTERRUPTS_CHAIN -Cyg_Interrupt *Cyg_Interrupt::chain_list[CYG_ISR_COUNT]; +Cyg_Interrupt *Cyg_Interrupt::chain_list[CYGNUM_HAL_ISR_COUNT]; #endif @@ -264,7 +318,8 @@ Cyg_Interrupt *Cyg_Interrupt::chain_list #ifdef CYGIMP_KERNEL_INTERRUPTS_CHAIN -cyg_uint32 Cyg_Interrupt::chain_isr(cyg_vector vector, CYG_ADDRWORD data) +cyg_uint32 +Cyg_Interrupt::chain_isr(cyg_vector vector, CYG_ADDRWORD data) { Cyg_Interrupt *p = *(Cyg_Interrupt **)data; @@ -276,9 +331,9 @@ cyg_uint32 Cyg_Interrupt::chain_isr(cyg_ { register cyg_uint32 isr_ret = p->isr(vector, p->data); - if( isr_ret & 2 ) p->post_dsr(); + if( isr_ret & Cyg_Interrupt::CALL_DSR ) p->post_dsr(); - if( isr_ret & 1 ) break; + if( isr_ret & Cyg_Interrupt::HANDLED ) break; } p = p->next; @@ -292,12 +347,13 @@ cyg_uint32 Cyg_Interrupt::chain_isr(cyg_ // ------------------------------------------------------------------------- // Attach an ISR to an interrupt vector. -void Cyg_Interrupt::attach() +void +Cyg_Interrupt::attach(void) { CYG_REPORT_FUNCTION(); - CYG_ASSERT( vector >= CYG_ISR_MIN, "Invalid vector"); - CYG_ASSERT( vector <= CYG_ISR_MAX, "Invalid vector"); + CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector"); + CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector"); CYG_INSTRUMENT_INTR(ATTACH, vector, 0); @@ -313,11 +369,14 @@ void Cyg_Interrupt::attach() 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 @@ -341,20 +400,30 @@ void Cyg_Interrupt::attach() #else - HAL_INTERRUPT_ATTACH( vector, isr, data, this ); + { + 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_Interrupt::detach(void) { CYG_REPORT_FUNCTION(); - CYG_ASSERT( vector >= CYG_ISR_MIN, "Invalid vector"); - CYG_ASSERT( vector <= CYG_ISR_MAX, "Invalid vector"); + CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector"); + CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector"); CYG_INSTRUMENT_INTR(DETACH, vector, 0); @@ -362,7 +431,11 @@ void Cyg_Interrupt::detach() // Remove the interrupt object from the vector chain. - Cyg_Interrupt **p = &chain_list[vector]; + cyg_uint32 index; + + HAL_TRANSLATE_VECTOR( vector, index ); + + Cyg_Interrupt **p = &chain_list[index]; while( *p != NULL ) { @@ -379,7 +452,7 @@ void Cyg_Interrupt::detach() // If this was the last one, detach the vector. - if( chain_list[vector] == NULL ) + if( chain_list[index] == NULL ) HAL_INTERRUPT_DETACH( vector, chain_isr ); #else @@ -387,33 +460,44 @@ void Cyg_Interrupt::detach() 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) +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 >= CYG_VSR_MIN, "Invalid vector"); - CYG_ASSERT( vector <= CYG_VSR_MAX, "Invalid vector"); + 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) +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 >= CYG_VSR_MIN, "Invalid vector"); - CYG_ASSERT( vector <= CYG_VSR_MAX, "Invalid vector"); + CYG_ASSERT( vector >= CYGNUM_HAL_VSR_MIN, "Invalid vector"); + CYG_ASSERT( vector <= CYGNUM_HAL_VSR_MAX, "Invalid vector"); CYG_INTERRUPT_STATE old_ints; @@ -422,78 +506,103 @@ void Cyg_Interrupt::set_vsr(cyg_vector v 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_Interrupt::disable_interrupts(void) { CYG_REPORT_FUNCTION(); - CYG_INSTRUMENT_INTR(DISABLE, 0, 0); + CYG_INSTRUMENT_INTR(DISABLE, disable_counter+1, 0); CYG_INTERRUPT_STATE dummy; HAL_DISABLE_INTERRUPTS(dummy); - // Keep a disable level counter?? + CYG_ASSERT( disable_counter >= 0 , "Disable counter negative"); + + disable_counter++; + + CYG_REPORT_RETURN(); } // ------------------------------------------------------------------------- // Re-enable CPU interrupts -void Cyg_Interrupt::enable_interrupts() +void +Cyg_Interrupt::enable_interrupts(void) { CYG_REPORT_FUNCTION(); - CYG_INSTRUMENT_INTR(ENABLE, 0, 0); + CYG_INSTRUMENT_INTR(ENABLE, disable_counter, 0); + + CYG_ASSERT( disable_counter > 0 , "Disable counter not greater than zero"); + + disable_counter--; - HAL_ENABLE_INTERRUPTS(); + if ( disable_counter == 0 ) + { + HAL_ENABLE_INTERRUPTS(); + } + + CYG_REPORT_RETURN(); } // ------------------------------------------------------------------------- // Mask a specific interrupt in a PIC -void Cyg_Interrupt::mask_interrupt(cyg_vector vector) +void +Cyg_Interrupt::mask_interrupt(cyg_vector vector) { CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG1("vector=%d", vector); - CYG_ASSERT( vector >= CYG_ISR_MIN, "Invalid vector"); - CYG_ASSERT( vector <= CYG_ISR_MAX, "Invalid 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 ) + HAL_INTERRUPT_MASK( vector ); + + CYG_REPORT_RETURN(); } // ------------------------------------------------------------------------- // Clear PIC mask -void Cyg_Interrupt::unmask_interrupt(cyg_vector vector) +void +Cyg_Interrupt::unmask_interrupt(cyg_vector vector) { CYG_REPORT_FUNCTION(); - CYG_ASSERT( vector >= CYG_ISR_MIN, "Invalid vector"); - CYG_ASSERT( vector <= CYG_ISR_MAX, "Invalid vector"); + 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) +void +Cyg_Interrupt::acknowledge_interrupt(cyg_vector vector) { // CYG_REPORT_FUNCTION(); - CYG_ASSERT( vector >= CYG_ISR_MIN, "Invalid vector"); - CYG_ASSERT( vector <= CYG_ISR_MAX, "Invalid vector"); + CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector"); + CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector"); CYG_INSTRUMENT_INTR(ACK, vector, 0); @@ -503,20 +612,25 @@ void Cyg_Interrupt::acknowledge_interrup // ------------------------------------------------------------------------- // Change interrupt detection at PIC -void Cyg_Interrupt::configure_interrupt( +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 >= CYG_ISR_MIN, "Invalid vector"); - CYG_ASSERT( vector <= CYG_ISR_MAX, "Invalid vector"); + 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(); } // -------------------------------------------------------------------------
