URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [trunk/] [ecos-2.0/] [packages/] [kernel/] [v2_0/] [include/] [intr.hxx] - Rev 1765
Compare with Previous | Blame | View Log
#ifndef CYGONCE_KERNEL_INTR_HXX#define CYGONCE_KERNEL_INTR_HXX//==========================================================================//// intr.hxx//// Interrupt class declaration(s)////==========================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.//// 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// 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// WARRANTY; without even the implied warranty of MERCHANTABILITY or// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License// for more details.//// You should have received a copy of the GNU General Public License along// with eCos; if not, write to the Free Software Foundation, Inc.,// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.//// 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// 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// License. However the source code for this file must still be made available// 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 file might be covered by the GNU General Public License.//// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.// at http://sources.redhat.com/ecos/ecos-license/// -------------------------------------------//####ECOSGPLCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s): nickg// Contributors: nickg// Date: 1997-09-09// Purpose: Define Interrupt class interfaces// Description: The classes defined here provide the APIs for handling// interrupts.// Usage: #include "intr.hxx"//////####DESCRIPTIONEND####////==========================================================================#include <cyg/kernel/ktypes.h>#include <cyg/kernel/smp.hxx>// -------------------------------------------------------------------------// Default definitions// Some HALs define the ISR table to be a different size to the number// of ISR vectors. These HALs will define CYGNUM_HAL_ISR_TABLE_SIZE. All// other HALs will have the table size equal to the number of vectors.#ifndef CYGNUM_HAL_ISR_TABLE_SIZE# define CYGNUM_HAL_ISR_TABLE_SIZE CYGNUM_HAL_ISR_COUNT#endif// -------------------------------------------------------------------------// Function prototype typedefs// VSR = Vector Service Routine. This is the code attached directly to an// interrupt vector. It is very architecture/platform specific and usually// must be written in assembler.typedef void cyg_VSR();// ISR = Interrupt Service Routine. This is called from the default// VSR in response to an interrupt. It may access shared data but may// not call kernel routines. The return value may be// Cyg_Interrupt::HANDLED and/or Cyg_Interrupt::CALL_DSR.typedef cyg_uint32 cyg_ISR(cyg_vector vector, CYG_ADDRWORD data);// DSR = Deferred Service Routine. This is called if the ISR returns// the Cyg_Interrupt::CALL_DSR bit. It is called at a "safe" point in// the kernel where it may make calls on kernel routines. The count// argument indicates how many times the ISR has asked for the DSR to// be posted since the last time the DSR ran.typedef void cyg_DSR(cyg_vector vector, cyg_ucount32 count, CYG_ADDRWORD data);// -------------------------------------------------------------------------// Include HAL definitionsclass Cyg_Interrupt;#include <cyg/hal/hal_arch.h>#include <cyg/hal/hal_intr.h>#ifndef HAL_INTERRUPT_STACK_CALL_PENDING_DSRS#define HAL_INTERRUPT_STACK_CALL_PENDING_DSRS() \Cyg_Interrupt::call_pending_DSRs_inner()#endifexternC void interrupt_end(cyg_uint32 isr_ret,Cyg_Interrupt *intr,HAL_SavedRegisters *ctx);externC void cyg_interrupt_post_dsr( CYG_ADDRWORD intr_obj );externC void cyg_interrupt_call_pending_DSRs( void );// -------------------------------------------------------------------------// Interrupt class. This both represents each interrupt and provides a static// interface for controlling the interrupt hardware.class Cyg_Interrupt{friend class Cyg_Scheduler;friend void interrupt_end( cyg_uint32,Cyg_Interrupt *,HAL_SavedRegisters *);friend void cyg_interrupt_post_dsr( CYG_ADDRWORD intr_obj );friend void cyg_interrupt_call_pending_DSRs( void );cyg_vector vector; // Interrupt vectorcyg_priority priority; // Queuing prioritycyg_ISR *isr; // Pointer to ISRcyg_DSR *dsr; // Pointer to DSRCYG_ADDRWORD data; // Data pointer// DSR handling interface called by the scheduler// Check for pending DSRsstatic cyg_bool DSRs_pending();// Call any pending DSRsstatic void call_pending_DSRs();static void call_pending_DSRs_inner();// DSR handling interface called by the scheduler and HAL// interrupt arbiters.void post_dsr(); // Post the DSR for this interrupt// Data structures for handling DSR calls. We implement two DSR// handling mechanisms, a list based one and a table based// one. The list based mechanism is safe with respect to temporary// overloads and will not run out of resource. However it requires// extra data per interrupt object, and interrupts must be turned// off briefly when delivering the DSR. The table based mechanism// does not need unnecessary interrupt switching, but may be prone// to overflow on overload. However, since a correctly programmed// real time application should not experience such a condition,// the table based mechanism is more efficient for real use. The// list based mechainsm is enabled by default since it is safer to// use during development.#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_TABLEstatic Cyg_Interrupt *dsr_table[CYGNUM_KERNEL_CPU_MAX][CYGNUM_KERNEL_INTERRUPTS_DSRS_TABLE_SIZE]CYGBLD_ANNOTATE_VARIABLE_INTR;static cyg_ucount32 dsr_table_head[CYGNUM_KERNEL_CPU_MAX]CYGBLD_ANNOTATE_VARIABLE_INTR;static volatile cyg_ucount32 dsr_table_tail[CYGNUM_KERNEL_CPU_MAX]CYGBLD_ANNOTATE_VARIABLE_INTR;#endif#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST// Number of DSR posts madevolatile cyg_ucount32 dsr_count CYGBLD_ANNOTATE_VARIABLE_INTR;// next DSR in listCyg_Interrupt* volatile next_dsr CYGBLD_ANNOTATE_VARIABLE_INTR;// static list of pending DSRsstatic Cyg_Interrupt* volatile dsr_list[CYGNUM_KERNEL_CPU_MAX]CYGBLD_ANNOTATE_VARIABLE_INTR;#endif#ifdef CYGIMP_KERNEL_INTERRUPTS_CHAIN// The default mechanism for handling interrupts is to attach just// one Interrupt object to each vector. In some cases, and on some// hardware, this is not possible, and each vector must carry a chain// of interrupts.Cyg_Interrupt *next; // Next Interrupt in list// Chaining ISR inserted in HAL vectorstatic cyg_uint32 chain_isr(cyg_vector vector, CYG_ADDRWORD data);// Table of interrupt chainsstatic Cyg_Interrupt *chain_list[CYGNUM_HAL_ISR_TABLE_SIZE];#endif// Interrupt disable data. Interrupt disable can be nested. On// each CPU this is controlled by disable_counter[cpu]. When the// counter is first incremented from zero to one, the// interrupt_disable_spinlock is claimed using spin_intsave(), the// original interrupt enable state being saved in// interrupt_disable_state[cpu]. When the counter is decremented// back to zero the spinlock is cleared using clear_intsave().// The spinlock is necessary in SMP systems since a thread// accessing data shared with an ISR may be scheduled on a// different CPU to the one that handles the interrupt. So, merely// blocking local interrupts would be ineffective. SMP aware// device drivers should either use their own spinlocks to protect// data, or use the API supported by this class, via// cyg_drv_isr_lock()/_unlock(). Note that it now becomes// essential that ISRs do this if they are to be SMP-compatible.// In a single CPU system, this mechanism reduces to just// disabling/enabling interrupts.// Disable level counter. This counts the number of times// interrupts have been disabled.static volatile cyg_int32 disable_counter[CYGNUM_KERNEL_CPU_MAX]CYGBLD_ANNOTATE_VARIABLE_INTR;// Interrupt disable spinlock. This is claimed by any CPU that has// disabled interrupts via the Cyg_Interrupt API.static Cyg_SpinLock interrupt_disable_spinlock CYGBLD_ANNOTATE_VARIABLE_INTR;// Saved interrupt state. When each CPU first disables interrupts// the original state of the interrupts are saved here to be// restored later.static CYG_INTERRUPT_STATE interrupt_disable_state[CYGNUM_KERNEL_CPU_MAX]CYGBLD_ANNOTATE_VARIABLE_INTR;public:Cyg_Interrupt // Initialize interrupt(cyg_vector vector, // Vector to attach tocyg_priority priority, // Queue priorityCYG_ADDRWORD data, // Data pointercyg_ISR *isr, // Interrupt Service Routinecyg_DSR *dsr // Deferred Service Routine);~Cyg_Interrupt();// ISR return valuesenum {HANDLED = 1, // Interrupt was handledCALL_DSR = 2 // Schedule DSR};// Interrupt managementvoid attach(); // Attach to vectorvoid detach(); // Detach from vector// Static Interrupt management functions// Get the current service routinestatic void get_vsr(cyg_vector vector, cyg_VSR **vsr);// Install a vector service routinestatic void set_vsr(cyg_vector vector, // hardware vector to replacecyg_VSR *vsr, // my new service routinecyg_VSR **old = NULL // pointer to old vsr, if required);// Static interrupt masking functions// Disable interrupts at the CPUstatic void disable_interrupts();// Re-enable CPU interruptsstatic void enable_interrupts();// Are interrupts enabled at the CPU?static inline cyg_bool interrupts_enabled(){return (0 == disable_counter[CYG_KERNEL_CPU_THIS()]);}// Get the vector for the following callsinline cyg_vector get_vector(){return vector;}// Static PIC control functions// Mask a specific interrupt in a PICstatic void mask_interrupt(cyg_vector vector);// The same but not interrupt safestatic void mask_interrupt_intunsafe(cyg_vector vector);// Clear PIC maskstatic void unmask_interrupt(cyg_vector vector);// The same but not interrupt safestatic void unmask_interrupt_intunsafe(cyg_vector vector);// Acknowledge interrupt at PICstatic void acknowledge_interrupt(cyg_vector vector);// Change interrupt detection at PICstatic void configure_interrupt(cyg_vector vector, // vector to controlcyg_bool level, // level or edge triggeredcyg_bool up // hi/lo level, rising/falling edge);#ifdef CYGPKG_KERNEL_SMP_SUPPORT// SMP support for associating an interrupt with a specific CPU.static void set_cpu( cyg_vector, HAL_SMP_CPU_TYPE cpu );static HAL_SMP_CPU_TYPE get_cpu( cyg_vector );#endif};#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS// -------------------------------------------------------------------------// Check for pending DSRsinline cyg_bool Cyg_Interrupt::DSRs_pending(){HAL_SMP_CPU_TYPE cpu = CYG_KERNEL_CPU_THIS();#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_TABLEreturn dsr_table_head[cpu] != dsr_table_tail[cpu];#endif#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_LISTreturn dsr_list[cpu] != NULL;#endif};#endif // CYGIMP_KERNEL_INTERRUPTS_DSRS// -------------------------------------------------------------------------#endif // ifndef CYGONCE_KERNEL_INTR_HXX// EOF intr.hxx
