/* * Defines and Macros for Interrupt-Service-Routines * collected and partly created by * Martin Thomas * * Copyright 2005 M. Thomas * No guarantees, warrantees, or promises, implied or otherwise. * May be used for hobby or commercial purposes provided copyright * notice remains intact. */ #ifndef interrupt_utils_ #define interrupt_utils_ /* The following defines are usefull for interrupt service routine declarations. */ /* RAMFUNC Attribute which defines a function to be located in memory section .fastrun and called via "long calls". See linker-skript and startup-code to see how the .fastrun-section is handled. The definition is not only useful for ISRs but since ISRs should be executed fast the macro is defined in this header. */ #define RAMFUNC __attribute__ ((long_call, section (".fastrun"))) /* INTFUNC standard attribute for arm-elf-gcc which marks a function as ISR (for the VIC). Since gcc seems to produce wrong code if this attribute is used in thumb/thumb-interwork the attribute should only be used for "pure ARM-mode" binaries. */ #define INTFUNC __attribute__ ((interrupt("IRQ"))) /* NACKEDFUNC gcc will not add any code to a function declared "nacked". The user has to take care to save registers and add the needed code for ISR functions. Some macros for this tasks are provided below. */ #define NACKEDFUNC __attribute__((naked)) /****************************************************************************** * * MACRO Name: ISR_STORE() * * Description: * This MACRO is used upon entry to an ISR with interrupt nesting. * Should be used together with ISR_ENABLE_NEST(). The MACRO * performs the following steps: * * 1 - Save the non-banked registers r0-r12 and lr onto the IRQ stack. * *****************************************************************************/ #define ISR_STORE() asm volatile( \ "STMDB SP!,{R0-R12,LR}\n" ) /****************************************************************************** * * MACRO Name: ISR_RESTORE() * * Description: * This MACRO is used upon exit from an ISR with interrupt nesting. * Should be used together with ISR_DISABLE_NEST(). The MACRO * performs the following steps: * * 1 - Load the non-banked registers r0-r12 and lr from the IRQ stack. * 2 - Adjusts resume adress * *****************************************************************************/ #define ISR_RESTORE() asm volatile( \ "LDMIA SP!,{R0-R12,LR}\n" \ "SUBS R15,R14,#0x0004\n" ) /****************************************************************************** * * MACRO Name: ISR_ENABLE_NEST() * * Description: * This MACRO is used upon entry from an ISR with interrupt nesting. * Should be used after ISR_STORE. * *****************************************************************************/ #define ISR_ENABLE_NEST() asm volatile( \ "MRS LR, SPSR \n" \ "STMFD SP!, {LR} \n" \ "MSR CPSR_c, #0x1f \n" \ "STMFD SP!, {LR} " ) /****************************************************************************** * * MACRO Name: ISR_DISABLE_NEST() * * Description: * This MACRO is used upon entry from an ISR with interrupt nesting. * Should be used before ISR_RESTORE. * *****************************************************************************/ #define ISR_DISABLE_NEST() asm volatile( \ "LDMFD SP!, {LR} \n" \ "MSR CPSR_c, #0x92 \n" \ "LDMFD SP!, {LR} \n" \ "MSR SPSR_cxsf, LR \n" ) /* * The following marcos are from the file "armVIC.h" by: * * Copyright 2004, R O SoftWare * No guarantees, warrantees, or promises, implied or otherwise. * May be used for hobby or commercial purposes provided copyright * notice remains intact. * */ /****************************************************************************** * * MACRO Name: ISR_ENTRY() * * Description: * This MACRO is used upon entry to an ISR. The current version of * the gcc compiler for ARM does not produce correct code for * interrupt routines to operate properly with THUMB code. The MACRO * performs the following steps: * * 1 - Adjust address at which execution should resume after servicing * ISR to compensate for IRQ entry * 2 - Save the non-banked registers r0-r12 and lr onto the IRQ stack. * 3 - Get the status of the interrupted program is in SPSR. * 4 - Push it onto the IRQ stack as well. * *****************************************************************************/ #define ISR_ENTRY() asm volatile(" sub lr, lr,#4\n" \ " stmfd sp!,{r0-r12,lr}\n" \ " mrs r1, spsr\n" \ " stmfd sp!,{r1}") /****************************************************************************** * * MACRO Name: ISR_EXIT() * * Description: * This MACRO is used to exit an ISR. The current version of the gcc * compiler for ARM does not produce correct code for interrupt * routines to operate properly with THUMB code. The MACRO performs * the following steps: * * 1 - Recover SPSR value from stack * 2 - and restore its value * 3 - Pop the return address & the saved general registers from * the IRQ stack & return * *****************************************************************************/ #define ISR_EXIT() asm volatile(" ldmfd sp!,{r1}\n" \ " msr spsr_c,r1\n" \ " ldmfd sp!,{r0-r12,pc}^") /****************************************************************************** * * Function Name: disableIRQ() * * Description: * This function sets the IRQ disable bit in the status register * * Calling Sequence: * void * * Returns: * previous value of CPSR * *****************************************************************************/ unsigned disableIRQ(void); /****************************************************************************** * * Function Name: enableIRQ() * * Description: * This function clears the IRQ disable bit in the status register * * Calling Sequence: * void * * Returns: * previous value of CPSR * *****************************************************************************/ unsigned enableIRQ(void); /****************************************************************************** * * Function Name: restoreIRQ() * * Description: * This function restores the IRQ disable bit in the status register * to the value contained within passed oldCPSR * * Calling Sequence: * void * * Returns: * previous value of CPSR * *****************************************************************************/ unsigned restoreIRQ(unsigned oldCPSR); /****************************************************************************** * * Function Name: disableFIQ() * * Description: * This function sets the FIQ disable bit in the status register * * Calling Sequence: * void * * Returns: * previous value of CPSR * *****************************************************************************/ unsigned disableFIQ(void); /****************************************************************************** * * Function Name: enableFIQ() * * Description: * This function clears the FIQ disable bit in the status register * * Calling Sequence: * void * * Returns: * previous value of CPSR * *****************************************************************************/ unsigned enableFIQ(void); /****************************************************************************** * * Function Name: restoreFIQ() * * Description: * This function restores the FIQ disable bit in the status register * to the value contained within passed oldCPSR * * Calling Sequence: * void * * Returns: * previous value of CPSR * *****************************************************************************/ unsigned restoreFIQ(unsigned oldCPSR); #endif