ihndlr_lpc2xxx.c

Go to the documentation of this file.
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   (*(uint32_t *)0x00000004L)   
00055 #define SOFTWARE_INTERRUPT_VECTOR_ADDR      (*(uint32_t *)0x00000008L)
00056 #define PREFETCH_ABORT_VECTOR_ADDR          (*(uint32_t *)0x0000000CL)
00057 #define DATA_ABORT_VECTOR_ADDR              (*(uint32_t *)0x00000010L)
00058 #define IRQ_VECTOR_ADDR                     (*(uint32_t *)0x00000018L)
00059 #define FIQ_VECTOR_ADDR                     (*(uint32_t *)0x0000001CL)
00060 
00061 #define DATA_ABORT_ISR_ADDR                 (*(uint32_t *)0x00000030L)
00062 #define IRQ_ISR_ADDR                        (*(uint32_t *)0x00000038L)
00063 #define FIQ_ISR_ADDR                        (*(uint32_t *)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 uint32_t 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    = (uint32_t)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    = (uint32_t)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    = (uint32_t)ABORTHandler;
00233 #endif  
00234 
00235   /*
00236    * Init the Vectored Interrupt Controller (VIC)
00237    */
00238   VICInit();
00239 } /* InitIrqHandler */
00240 
00241 /*** EOF ***/
00242 

© 2000-2010 by contributors - visit http://www.ethernut.de/