00001 /***************************************************************************** 00002 * irq.c: Interrupt handler C file for Philips LPC214x Family Microprocessors 00003 * 00004 * Copyright(C) 2006, Philips Semiconductor 00005 * All rights reserved. 00006 * 00007 * History 00008 * 2005.10.01 ver 1.00 Prelimnary version, first Release 00009 * 00010 ******************************************************************************/ 00011 #include "LPC214x.h" /* LPC23XX Peripheral Registers */ 00012 #include "irq.h" 00013 00014 #ifndef NULL 00015 #define NULL ((void *)0) 00016 #endif 00017 00018 #ifndef FALSE 00019 #define FALSE (0) 00020 #endif 00021 00022 #ifndef TRUE 00023 #define TRUE (1) 00024 #endif 00025 00026 00027 /****************************************************************************** 00028 ** Function name: DefaultVICHandler 00029 ** 00030 ** Descriptions: Default VIC interrupt handler. 00031 ** This handler is set to deal with spurious 00032 ** interrupt. 00033 ** If the IRQ service routine reads the VIC 00034 ** address register, and no IRQ slot responses 00035 ** as described above, this address is returned. 00036 ** parameters: None 00037 ** Returned value: None 00038 ** 00039 ******************************************************************************/ 00040 // mthomas: inserted static to avoid gcc-warning 00041 static void DefaultVICHandler (void) __irq 00042 { 00043 /* if the IRQ is not installed into the VIC, and interrupt occurs, the 00044 default interrupt VIC address will be used. This could happen in a race 00045 condition. For debugging, use this endless loop to trace back. */ 00046 /* For more details, see Philips appnote AN10414 */ 00047 VICVectAddr = 0; /* Acknowledge Interrupt */ 00048 while ( 1 ); 00049 } 00050 00051 /* Initialize the interrupt controller */ 00052 /****************************************************************************** 00053 ** Function name: init_VIC 00054 ** 00055 ** Descriptions: Initialize VIC interrupt controller. 00056 ** parameters: None 00057 ** Returned value: None 00058 ** 00059 ******************************************************************************/ 00060 void init_VIC(void) 00061 { 00062 unsigned long i = 0; 00063 unsigned long *vect_addr, *vect_cntl; 00064 00065 /* initialize VIC*/ 00066 VICIntEnClr = 0xffffffff; 00067 VICVectAddr = 0; 00068 VICIntSelect = 0; 00069 00070 /* set all the vector and vector control register to 0 */ 00071 for ( i = 0; i < VIC_SIZE; i++ ) 00072 { 00073 vect_addr = (unsigned long *)(VIC_BASE_ADDR + VECT_ADDR_INDEX + i*4); 00074 vect_cntl = (unsigned long *)(VIC_BASE_ADDR + VECT_CNTL_INDEX + i*4); 00075 *vect_addr = 0; 00076 *vect_cntl = 0; 00077 } 00078 00079 /* Install the default VIC handler here */ 00080 VICDefVectAddr = (unsigned long)DefaultVICHandler; 00081 return; 00082 } 00083 00084 /****************************************************************************** 00085 ** Function name: install_irq 00086 ** 00087 ** Descriptions: Install interrupt handler 00088 ** The max VIC size is 16, but, there are 32 interrupt 00089 ** request inputs. Not all of them can be installed into 00090 ** VIC table at the same time. 00091 ** The order of the interrupt request installation is 00092 ** first come first serve. 00093 ** parameters: Interrupt number and interrupt handler address 00094 ** Returned value: true or false, when the table is full, return false 00095 ** 00096 ******************************************************************************/ 00097 unsigned long install_irq( unsigned long IntNumber, void *HandlerAddr ) 00098 { 00099 unsigned long i; 00100 unsigned long *vect_addr; 00101 unsigned long *vect_cntl; 00102 00103 VICIntEnClr = 1 << IntNumber; /* Disable Interrupt */ 00104 00105 for ( i = 0; i < VIC_SIZE; i++ ) 00106 { 00107 /* find first un-assigned VIC address for the handler */ 00108 00109 vect_addr = (unsigned long *)(VIC_BASE_ADDR + VECT_ADDR_INDEX + i*4); 00110 vect_cntl = (unsigned long *)(VIC_BASE_ADDR + VECT_CNTL_INDEX + i*4); 00111 if ( *vect_addr == (unsigned long)NULL ) 00112 { 00113 *vect_addr = (unsigned long)HandlerAddr; /* set interrupt vector */ 00114 *vect_cntl = (unsigned long)(IRQ_SLOT_EN | IntNumber); 00115 break; 00116 } 00117 } 00118 if ( i == VIC_SIZE ) 00119 { 00120 return( FALSE ); /* fatal error, can't find empty vector slot */ 00121 } 00122 VICIntEnable = 1 << IntNumber; /* Enable Interrupt */ 00123 return( TRUE ); 00124 } 00125 00126 /****************************************************************************** 00127 ** Function name: uninstall_irq 00128 ** 00129 ** Descriptions: Uninstall interrupt handler 00130 ** Find the interrupt handler installed in the VIC 00131 ** based on the interrupt number, set the location 00132 ** back to NULL to uninstall it. 00133 ** parameters: Interrupt number 00134 ** Returned value: true or false, when the interrupt number is not found, 00135 ** return false 00136 ** 00137 ******************************************************************************/ 00138 unsigned long uninstall_irq( unsigned long IntNumber ) 00139 { 00140 unsigned long i; 00141 unsigned long *vect_addr; 00142 unsigned long *vect_cntl; 00143 00144 VICIntEnClr = 1 << IntNumber; /* Disable Interrupt */ 00145 00146 for ( i = 0; i < VIC_SIZE; i++ ) 00147 { 00148 /* find first un-assigned VIC address for the handler */ 00149 vect_addr = (unsigned long *)(VIC_BASE_ADDR + VECT_ADDR_INDEX + i*4); 00150 vect_cntl = (unsigned long *)(VIC_BASE_ADDR + VECT_CNTL_INDEX + i*4); 00151 if ( (*vect_cntl & ~IRQ_SLOT_EN ) == IntNumber ) 00152 { 00153 *vect_addr = (unsigned long)NULL; /* clear the VIC entry in the VIC table */ 00154 *vect_cntl &= ~IRQ_SLOT_EN; /* disable SLOT_EN bit */ 00155 break; 00156 } 00157 } 00158 if ( i == VIC_SIZE ) 00159 { 00160 return( FALSE ); /* fatal error, can't find interrupt number 00161 in vector slot */ 00162 } 00163 VICIntEnable = 1 << IntNumber; /* Enable Interrupt */ 00164 return( TRUE ); 00165 } 00166 00167 /****************************************************************************** 00168 ** End Of File 00169 ******************************************************************************/