interrupt-utils.h

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 

Generated on Mon Apr 11 14:23:34 2011 for Contiki 2.5 by  doxygen 1.6.1