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