00001 /* 00002 * Defines and Macros for Interrupt-Service-Routines 00003 * collected and partly created by 00004 * Martin Thomas <mthomas@rhrk.uni-kl.de> 00005 * 00006 * Copyright 2005 M. Thomas 00007 * No guarantees, warrantees, or promises, implied or otherwise. 00008 * May be used for hobby or commercial purposes provided copyright 00009 * notice remains intact. 00010 */ 00011 00012 /* 00013 Warning: The enable- and disable-functions can not be used 00014 in USR-mode which is the default for the Philips-examples 00015 (see Startup.S). cpsr can not be written in USR-mode. 00016 If you need to enable or disable interrupts use the 00017 SWI-calls (see example SWI/swi.c/swi_handler.S). The 00018 functions can be used in SYS-mode to start the system 00019 in SYS-mode the startup-code must be changed. 00020 00021 The macros in this file are useful if interrupt-service-routines 00022 when using thumb-mode and/or optimisation without an addtional 00023 "assembler-wrapper". The gcc-attribute interrupt("IRQ") does 00024 not work reliably here. See timer.c for an example implementation 00025 of an ISR that uses macros. For the gcc-port of the Philips-examples 00026 the macros are not needed, all functionality has been integrated 00027 into isr_wrapper (see Startup.S). 00028 */ 00029 00030 #ifndef interrupt_utils_ 00031 #define interrupt_utils_ 00032 00033 /* 00034 The following defines are usefull for 00035 interrupt service routine declarations. 00036 */ 00037 00038 /* 00039 RAMFUNC 00040 Attribute which defines a function to be located 00041 in memory section .fastrun and called via "long calls". 00042 See linker-skript and startup-code to see how the 00043 .fastrun-section is handled. 00044 The definition is not only useful for ISRs but since 00045 ISRs should be executed fast the macro is defined in 00046 this header. 00047 */ 00048 #define RAMFUNC __attribute__ ((long_call, section (".fastrun"))) 00049 00050 00051 /* 00052 INTFUNC 00053 standard attribute for arm-elf-gcc which marks 00054 a function as ISR (for the VIC). Since gcc seems 00055 to produce wrong code if this attribute is used in 00056 thumb/thumb-interwork and/or activated optimisation 00057 the attribute should only be used for "pure ARM-mode" 00058 binaries. 00059 */ 00060 #define INTFUNC __attribute__ ((interrupt("IRQ"))) 00061 00062 00063 /* 00064 NACKEDFUNC 00065 gcc will not add any code to a function declared 00066 "nacked". The user has to take care to save registers 00067 and add the needed code for ISR functions. Some 00068 macros for this tasks are provided below. 00069 */ 00070 #define NACKEDFUNC __attribute__((naked)) 00071 00072 00073 /****************************************************************************** 00074 * 00075 * MACRO Name: ISR_STORE() 00076 * 00077 * Description: 00078 * This MACRO is used upon entry to an ISR with interrupt nesting. 00079 * Should be used together with ISR_ENABLE_NEST(). The MACRO 00080 * performs the following steps: 00081 * 00082 * 1 - Save the non-banked registers r0-r12 and lr onto the IRQ stack. 00083 * 00084 *****************************************************************************/ 00085 #define ISR_STORE() asm volatile( \ 00086 "STMDB SP!,{R0-R12,LR}\n" ) 00087 00088 /****************************************************************************** 00089 * 00090 * MACRO Name: ISR_RESTORE() 00091 * 00092 * Description: 00093 * This MACRO is used upon exit from an ISR with interrupt nesting. 00094 * Should be used together with ISR_DISABLE_NEST(). The MACRO 00095 * performs the following steps: 00096 * 00097 * 1 - Load the non-banked registers r0-r12 and lr from the IRQ stack. 00098 * 2 - Adjusts resume adress 00099 * 00100 *****************************************************************************/ 00101 #define ISR_RESTORE() asm volatile( \ 00102 "LDMIA SP!,{R0-R12,LR}\n" \ 00103 "SUBS R15,R14,#0x0004\n" ) 00104 00105 /****************************************************************************** 00106 * 00107 * MACRO Name: ISR_ENABLE_NEST() 00108 * 00109 * Description: 00110 * This MACRO is used upon entry from an ISR with interrupt nesting. 00111 * Should be used after ISR_STORE. 00112 * 00113 *****************************************************************************/ 00114 #define ISR_ENABLE_NEST() asm volatile( \ 00115 "MRS LR, SPSR \n" \ 00116 "STMFD SP!, {LR} \n" \ 00117 "MSR CPSR_c, #0x1F \n" \ 00118 "STMFD SP!, {LR} " ) 00119 00120 /****************************************************************************** 00121 * 00122 * MACRO Name: ISR_DISABLE_NEST() 00123 * 00124 * Description: 00125 * This MACRO is used upon entry from an ISR with interrupt nesting. 00126 * Should be used before ISR_RESTORE. 00127 * 00128 *****************************************************************************/ 00129 #define ISR_DISABLE_NEST() asm volatile( \ 00130 "LDMFD SP!, {LR} \n" \ 00131 "MSR CPSR_c, #0x92 \n" \ 00132 "LDMFD SP!, {LR} \n" \ 00133 "MSR SPSR_cxsf, LR \n" ) 00134 00135 00136 00137 /* 00138 * The following marcos are from the file "armVIC.h" by: 00139 * 00140 * Copyright 2004, R O SoftWare 00141 * No guarantees, warrantees, or promises, implied or otherwise. 00142 * May be used for hobby or commercial purposes provided copyright 00143 * notice remains intact. 00144 * 00145 */ 00146 00147 /****************************************************************************** 00148 * 00149 * MACRO Name: ISR_ENTRY() 00150 * 00151 * Description: 00152 * This MACRO is used upon entry to an ISR. The current version of 00153 * the gcc compiler for ARM does not produce correct code for 00154 * interrupt routines to operate properly with THUMB code. The MACRO 00155 * performs the following steps: 00156 * 00157 * 1 - Adjust address at which execution should resume after servicing 00158 * ISR to compensate for IRQ entry 00159 * 2 - Save the non-banked registers r0-r12 and lr onto the IRQ stack. 00160 * 3 - Get the status of the interrupted program is in SPSR. 00161 * 4 - Push it onto the IRQ stack as well. 00162 * 00163 *****************************************************************************/ 00164 #define ISR_ENTRY() asm volatile(" sub lr, lr,#4\n" \ 00165 " stmfd sp!,{r0-r12,lr}\n" \ 00166 " mrs r1, spsr\n" \ 00167 " stmfd sp!,{r1}") 00168 00169 /****************************************************************************** 00170 * 00171 * MACRO Name: ISR_EXIT() 00172 * 00173 * Description: 00174 * This MACRO is used to exit an ISR. The current version of the gcc 00175 * compiler for ARM does not produce correct code for interrupt 00176 * routines to operate properly with THUMB code. The MACRO performs 00177 * the following steps: 00178 * 00179 * 1 - Recover SPSR value from stack 00180 * 2 - and restore its value 00181 * 3 - Pop the return address & the saved general registers from 00182 * the IRQ stack & return 00183 * 00184 *****************************************************************************/ 00185 #define ISR_EXIT() asm volatile(" ldmfd sp!,{r1}\n" \ 00186 " msr spsr_c,r1\n" \ 00187 " ldmfd sp!,{r0-r12,pc}^") 00188 00189 /****************************************************************************** 00190 * 00191 * Function Name: disableIRQ() 00192 * 00193 * Description: 00194 * This function sets the IRQ disable bit in the status register 00195 * 00196 * Calling Sequence: 00197 * void 00198 * 00199 * Returns: 00200 * previous value of CPSR 00201 * 00202 *****************************************************************************/ 00203 unsigned disableIRQ(void); 00204 00205 /****************************************************************************** 00206 * 00207 * Function Name: enableIRQ() 00208 * 00209 * Description: 00210 * This function clears the IRQ disable bit in the status register 00211 * 00212 * Calling Sequence: 00213 * void 00214 * 00215 * Returns: 00216 * previous value of CPSR 00217 * 00218 *****************************************************************************/ 00219 unsigned enableIRQ(void); 00220 00221 /****************************************************************************** 00222 * 00223 * Function Name: restoreIRQ() 00224 * 00225 * Description: 00226 * This function restores the IRQ disable bit in the status register 00227 * to the value contained within passed oldCPSR 00228 * 00229 * Calling Sequence: 00230 * void 00231 * 00232 * Returns: 00233 * previous value of CPSR 00234 * 00235 *****************************************************************************/ 00236 unsigned restoreIRQ(unsigned oldCPSR); 00237 00238 /****************************************************************************** 00239 * 00240 * Function Name: disableFIQ() 00241 * 00242 * Description: 00243 * This function sets the FIQ disable bit in the status register 00244 * 00245 * Calling Sequence: 00246 * void 00247 * 00248 * Returns: 00249 * previous value of CPSR 00250 * 00251 *****************************************************************************/ 00252 unsigned disableFIQ(void); 00253 00254 /****************************************************************************** 00255 * 00256 * Function Name: enableFIQ() 00257 * 00258 * Description: 00259 * This function clears the FIQ disable bit in the status register 00260 * 00261 * Calling Sequence: 00262 * void 00263 * 00264 * Returns: 00265 * previous value of CPSR 00266 * 00267 *****************************************************************************/ 00268 unsigned enableFIQ(void); 00269 00270 /****************************************************************************** 00271 * 00272 * Function Name: restoreFIQ() 00273 * 00274 * Description: 00275 * This function restores the FIQ disable bit in the status register 00276 * to the value contained within passed oldCPSR 00277 * 00278 * Calling Sequence: 00279 * void 00280 * 00281 * Returns: 00282 * previous value of CPSR 00283 * 00284 *****************************************************************************/ 00285 unsigned restoreFIQ(unsigned oldCPSR); 00286 00287 00288 #endif 00289