📄 intr.cxx
字号:
//==========================================================================//// intr/intr.cxx//// Interrupt class implementations////==========================================================================//####COPYRIGHTBEGIN####//// -------------------------------------------// The contents of this file are subject to the Cygnus eCos Public License// Version 1.0 (the "License"); you may not use this file except in// compliance with the License. You may obtain a copy of the License at// http://sourceware.cygnus.com/ecos// // Software distributed under the License is distributed on an "AS IS"// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the// License for the specific language governing rights and limitations under// the License.// // The Original Code is eCos - Embedded Cygnus Operating System, released// September 30, 1998.// // The Initial Developer of the Original Code is Cygnus. Portions created// by Cygnus are Copyright (C) 1998,1999 Cygnus Solutions. All Rights Reserved.// -------------------------------------------////####COPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s): nickg// Contributors: nickg// Date: 1999-02-17// Purpose: Interrupt class implementation// Description: This file contains the definitions of the interrupt// class.////####DESCRIPTIONEND####////==========================================================================#include <pkgconf/kernel.h>#include <cyg/kernel/ktypes.h> // base kernel types#include <cyg/infra/cyg_trac.h> // tracing macros#include <cyg/infra/cyg_ass.h> // assertion macros#include <cyg/kernel/instrmnt.h> // instrumentation#include <cyg/kernel/intr.hxx> // our header#include <cyg/kernel/sched.hxx> // scheduler#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 cyg_priority pri, // Queue priority CYG_ADDRWORD d, // Data pointer cyg_ISR *ir, // Interrupt Service Routine 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; dsr = dr; data = d;#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST dsr_count = 0; next_dsr = NULL;#endif#ifdef CYGIMP_KERNEL_INTERRUPTS_CHAIN next = NULL; #endif CYG_REPORT_RETURN(); };// -------------------------------------------------------------------------Cyg_Interrupt::~Cyg_Interrupt(){ CYG_REPORT_FUNCTION(); detach(); CYG_REPORT_RETURN();};// -------------------------------------------------------------------------// DSR handling statics:#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_TABLECyg_Interrupt *Cyg_Interrupt::dsr_table[CYGNUM_KERNEL_INTERRUPTS_DSRS_TABLE_SIZE];cyg_ucount32 Cyg_Interrupt::dsr_table_head = 0;cyg_ucount32 Cyg_Interrupt::dsr_table_tail = 0;#endif#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_LISTCyg_Interrupt *Cyg_Interrupt::dsr_list = NULL;#endif// -------------------------------------------------------------------------// Call any pending DSRsvoidCyg_Interrupt::call_pending_DSRs_inner(void){// CYG_REPORT_FUNCTION();#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_TABLE while( dsr_table_head != dsr_table_tail ) { Cyg_Interrupt *intr = dsr_table[dsr_table_head]; dsr_table_head++; if( dsr_table_head >= CYGNUM_KERNEL_INTERRUPTS_DSRS_TABLE_SIZE ) dsr_table_head = 0; CYG_INSTRUMENT_INTR(CALL_DSR, intr->vector, 0); intr->dsr( intr->vector, 1, (CYG_ADDRWORD)intr->data ); } #endif#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST while( dsr_list != NULL ) { Cyg_Interrupt *intr; cyg_uint32 old_intr; cyg_count32 count; HAL_DISABLE_INTERRUPTS(old_intr); intr = dsr_list; dsr_list = intr->next_dsr; count = intr->dsr_count; intr->dsr_count = 0; HAL_RESTORE_INTERRUPTS(old_intr); intr->dsr( intr->vector, count, (CYG_ADDRWORD)intr->data ); } #endif };externC voidcyg_interrupt_call_pending_DSRs(void){ Cyg_Interrupt::call_pending_DSRs_inner();}// This function will be provided by HALs that fully implement// interrupt stack functionalityexternC void hal_interrupt_stack_call_pending_DSRs(void) __attribute__ ((weak, alias("cyg_interrupt_call_pending_DSRs")));voidCyg_Interrupt::call_pending_DSRs(void){ hal_interrupt_stack_call_pending_DSRs();}// -------------------------------------------------------------------------voidCyg_Interrupt::post_dsr(void){// CYG_REPORT_FUNCTION(); CYG_INSTRUMENT_INTR(POST_DSR, vector, 0); cyg_uint32 old_intr; // We need to disable interrupts during this part to // guard against nested interrupts. HAL_DISABLE_INTERRUPTS(old_intr);#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_TABLE dsr_table[dsr_table_tail++] = this; if( dsr_table_tail >= CYGNUM_KERNEL_INTERRUPTS_DSRS_TABLE_SIZE ) dsr_table_tail = 0;#endif#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST // Only add the interrupt to the dsr list if this is // the first DSR call. // At present DSRs are pushed onto the list and will be // called in reverse order. We do not define the order // in which DSRs are called, so this is acceptable. if( dsr_count++ == 0 ) { next_dsr = dsr_list; dsr_list = this; } #endif HAL_RESTORE_INTERRUPTS(old_intr); };// -------------------------------------------------------------------------// A C callable interface to Cyg_Interrupt::post_dsr() that can be used from// the HAL.externC voidcyg_interrupt_post_dsr( CYG_ADDRWORD intr_obj ){ Cyg_Interrupt* intr = (Cyg_Interrupt*) intr_obj; intr->post_dsr ();}// -------------------------------------------------------------------------// FIXME: should have better name - JiflexternC voidinterrupt_end( cyg_uint32 isr_ret, Cyg_Interrupt *intr, HAL_SavedRegisters *regs ){// CYG_REPORT_FUNCTION(); // 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 & Cyg_Interrupt::CALL_DSR && intr != NULL ) intr->post_dsr();#endif #ifdef CYGDBG_KERNEL_DEBUG_GDB_THREAD_SUPPORT // If we have GDB support enabled, and there is the possibility // that this thread will be context switched as a result of this // interrupt, then save the pointer to the saved thread context in // the thread object so that GDB can get a meaningful context to // look at. Cyg_Scheduler::get_current_thread()->set_saved_context(regs); #endif // Now unlock the scheduler, which may also call DSRs // and cause a thread switch to happen. Cyg_Scheduler::unlock();#ifdef CYGDBG_KERNEL_DEBUG_GDB_THREAD_SUPPORT Cyg_Scheduler::get_current_thread()->set_saved_context(0); #endif CYG_INSTRUMENT_INTR(RESTORE, vector, 0); }// -------------------------------------------------------------------------// Interrupt chaining statics.#ifdef CYGIMP_KERNEL_INTERRUPTS_CHAINCyg_Interrupt *Cyg_Interrupt::chain_list[CYGNUM_HAL_ISR_COUNT];#endif// -------------------------------------------------------------------------// Chaining ISR inserted in HAL vector#ifdef CYGIMP_KERNEL_INTERRUPTS_CHAIN
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -