00001 /**************************************************************************** 00002 * This file is part of the Ethernut port for the LPC2XXX 00003 * 00004 * Copyright (c) 2005 by Michael Fischer. All rights reserved. 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions 00008 * are met: 00009 * 00010 * 1. Redistributions of source code must retain the above copyright 00011 * notice, this list of conditions and the following disclaimer. 00012 * 2. Redistributions in binary form must reproduce the above copyright 00013 * notice, this list of conditions and the following disclaimer in the 00014 * documentation and/or other materials provided with the distribution. 00015 * 3. Neither the name of the author nor the names of its contributors may 00016 * be used to endorse or promote products derived from this software 00017 * without specific prior written permission. 00018 * 00019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00020 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00021 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00022 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 00023 * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00024 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00025 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 00026 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 00027 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00028 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 00029 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00030 * SUCH DAMAGE. 00031 * 00032 **************************************************************************** 00033 * 00034 * History: 00035 * 00036 * 24.09.05 mifi First Version 00037 * The CrossWorks for ARM toolchain will be used. Some of 00038 * this functions looks similar like my ARM uC/OS port for 00039 * CrossWorks because I have done it before (AN-1711B). 00040 * For some bit definition and information, take a look 00041 * in the LPC2119/2129/2194/2292/2294 user manual 2004 May 03. 00042 ****************************************************************************/ 00043 #define __IHNDLR_LPC2XXX_C__ 00044 00045 #include <arch/arm/lpc2xxx.h> 00046 #include <stdio.h> 00047 00048 /*=========================================================================*/ 00049 /* DEFINE: All Structures and Common Constants */ 00050 /*=========================================================================*/ 00051 /* 00052 * Take a look in the LPC2294 user manual (2004 May 03) page 52 00053 */ 00054 #define UNDEFINED_INSTRUCTION_VECTOR_ADDR (*(u_long *)0x00000004L) 00055 #define SOFTWARE_INTERRUPT_VECTOR_ADDR (*(u_long *)0x00000008L) 00056 #define PREFETCH_ABORT_VECTOR_ADDR (*(u_long *)0x0000000CL) 00057 #define DATA_ABORT_VECTOR_ADDR (*(u_long *)0x00000010L) 00058 #define IRQ_VECTOR_ADDR (*(u_long *)0x00000018L) 00059 #define FIQ_VECTOR_ADDR (*(u_long *)0x0000001CL) 00060 00061 #define DATA_ABORT_ISR_ADDR (*(u_long *)0x00000030L) 00062 #define IRQ_ISR_ADDR (*(u_long *)0x00000038L) 00063 #define FIQ_ISR_ADDR (*(u_long *)0x0000003CL) 00064 00065 typedef void (*FNCPTR)(void); 00066 00067 /*=========================================================================*/ 00068 /* DEFINE: Definition of all local Data */ 00069 /*=========================================================================*/ 00070 00071 /*=========================================================================*/ 00072 /* DEFINE: Definition of all local Procedures */ 00073 /*=========================================================================*/ 00074 /***************************************************************************/ 00075 /* VICInit */ 00076 /* */ 00077 /* This function will "init" the VIC. */ 00078 /* */ 00079 /* In : none */ 00080 /* Out : none */ 00081 /* Return: none */ 00082 /***************************************************************************/ 00083 static void VICInit (void) 00084 { 00085 /* 00086 * Disable ALL interrupts 00087 */ 00088 VICIntEnClr = 0xFFFFFFFF; 00089 00090 /* 00091 * VIC register can be accessed in 00092 * User or privileged mode. 00093 */ 00094 VICProtection = 0; 00095 00096 /* 00097 * All interrupts assigned to IRQ category 00098 */ 00099 VICIntSelect = 0; 00100 } /* VICInit */ 00101 00102 /***************************************************************************/ 00103 /* ABORTHandler */ 00104 /* */ 00105 /* This is the ABORT handler. */ 00106 /* */ 00107 /* In : none */ 00108 /* Out : none */ 00109 /* Return: none */ 00110 /***************************************************************************/ 00111 static void ABORTHandler(void) __attribute__ ((interrupt ("IRQ"))); 00112 static void ABORTHandler (void) 00113 { 00114 /* 00115 * The next lines are only used for debugging purpose 00116 */ 00117 volatile u_long AbortCounter = 0; 00118 00119 AbortCounter++; 00120 } /* ABORTHandler */ 00121 00122 /***************************************************************************/ 00123 /* IRQHandler */ 00124 /* */ 00125 /* This is the IRQ handler. If an IRQ occurred, the address of the */ 00126 /* ISR can be read from the VICVectAddr. */ 00127 /* */ 00128 /* 1. Read the address of the IRQHandler to execute from VICVectAddr */ 00129 /* 2. But check if the address is NOT 0. */ 00130 /* 3. Jump to the IRQHandler */ 00131 /* 4. Read VICVectAddr again to check if more interrupts are available */ 00132 /* to execute. */ 00133 /* */ 00134 /* In : none */ 00135 /* Out : none */ 00136 /* Return: none */ 00137 /***************************************************************************/ 00138 static void IRQHandler(void) __attribute__ ((interrupt ("IRQ"))); 00139 static void IRQHandler (void) 00140 { 00141 FNCPTR fncptr; 00142 00143 fncptr = (FNCPTR)VICVectAddr; /* 1 */ 00144 while (fncptr != (FNCPTR)0) { /* 2 */ 00145 (*fncptr)(); /* 3 */ 00146 fncptr = (FNCPTR)VICVectAddr; /* 4 */ 00147 } 00148 } /* IRQHandler */ 00149 00150 /***************************************************************************/ 00151 /* FIQHandler */ 00152 /* */ 00153 /* This is the FIQ handler. If an FIQ occurred, the address of the */ 00154 /* ISR can be read from the VICVectAddr */ 00155 /* */ 00156 /* 1. Read the address of the IRQHandler to execute from VICVectAddr */ 00157 /* 2. But check if the address is NOT 0. */ 00158 /* 3. Jump to the IRQHandler */ 00159 /* 4. Read VICVectAddr again to check if more interrupts are available */ 00160 /* to execute. */ 00161 /* */ 00162 /* In : none */ 00163 /* Out : none */ 00164 /* Return: none */ 00165 /***************************************************************************/ 00166 static void FIQHandler(void) __attribute__ ((interrupt ("FIQ"))); 00167 static void FIQHandler (void) 00168 { 00169 FNCPTR fncptr; 00170 00171 fncptr = (FNCPTR)VICVectAddr; /* 1 */ 00172 while (fncptr != (FNCPTR)0) { /* 2 */ 00173 (*fncptr)(); /* 3 */ 00174 fncptr = (FNCPTR)VICVectAddr; /* 4 */ 00175 } 00176 } /* FIQHandler */ 00177 00178 /*=========================================================================*/ 00179 /* DEFINE: All code exported */ 00180 /*=========================================================================*/ 00181 /***************************************************************************/ 00182 /* InitIrqHandler */ 00183 /* */ 00184 /* We will map the ARM interrupt vectors to the RAM. */ 00185 /* With this trick, the interrupt latency is a less than from flash. */ 00186 /* */ 00187 /* In : none */ 00188 /* Out : none */ 00189 /* Return: none */ 00190 /***************************************************************************/ 00191 void InitIrqHandler (void) 00192 { 00193 /* 00194 * User RAM Mode. Interrupt vecors are re-mapped to Static RAM. 00195 */ 00196 MEMMAP = 2; 00197 00198 /* 00199 * I got the information how to setup the interrupt 00200 * handler from the uC/OS port for the ARM. Take a look 00201 * in the application note AN-1014 from micrium. 00202 * (www.micrium.com) 00203 */ 00204 00205 /* 00206 * Set IRQHandler 00207 */ 00208 IRQ_VECTOR_ADDR = 0xE59FF018; /* LDR PC,[PC,#0x18] instruction */ 00209 IRQ_ISR_ADDR = (u_long)IRQHandler; /* IRQ exception vector address */ 00210 00211 /* 00212 * Set FIQHandler 00213 */ 00214 FIQ_VECTOR_ADDR = 0xE59FF018; /* LDR PC,[PC,#0x18] instruction */ 00215 FIQ_ISR_ADDR = (u_long)FIQHandler; /* FIQ exception vector address */ 00216 00217 /* 00218 * We does not need the next interrupt sources in the moment, 00219 * therefore jump to itself. 00220 */ 00221 UNDEFINED_INSTRUCTION_VECTOR_ADDR = 0xEAFFFFFE; 00222 SOFTWARE_INTERRUPT_VECTOR_ADDR = 0xEAFFFFFE; 00223 PREFETCH_ABORT_VECTOR_ADDR = 0xEAFFFFFE; 00224 00225 /* 00226 * In case we must find an ABORT error, 00227 * enable the next lines and set a breakpoint 00228 * in ABORTHandler. 00229 */ 00230 #if 1 00231 DATA_ABORT_VECTOR_ADDR = 0xE59FF018; 00232 DATA_ABORT_ISR_ADDR = (u_long)ABORTHandler; 00233 #endif 00234 00235 /* 00236 * Init the Vectored Interrupt Controller (VIC) 00237 */ 00238 VICInit(); 00239 } /* InitIrqHandler */ 00240 00241 /*** EOF ***/ 00242