Contiki 2.5
interrupt-utils.h
1 /*
2  * Defines and Macros for Interrupt-Service-Routines
3  * collected and partly created by
4  * Martin Thomas <mthomas@rhrk.uni-kl.de>
5  *
6  * Copyright 2005 M. Thomas
7  * No guarantees, warrantees, or promises, implied or otherwise.
8  * May be used for hobby or commercial purposes provided copyright
9  * notice remains intact.
10  */
11 
12 #ifndef interrupt_utils_
13 #define interrupt_utils_
14 
15 /*
16  The following defines are usefull for
17  interrupt service routine declarations.
18 */
19 
20 /*
21  RAMFUNC
22  Attribute which defines a function to be located
23  in memory section .fastrun and called via "long calls".
24  See linker-skript and startup-code to see how the
25  .fastrun-section is handled.
26  The definition is not only useful for ISRs but since
27  ISRs should be executed fast the macro is defined in
28  this header.
29 */
30 #define RAMFUNC __attribute__ ((long_call, section (".fastrun")))
31 
32 
33 /*
34  INTFUNC
35  standard attribute for arm-elf-gcc which marks
36  a function as ISR (for the VIC). Since gcc seems
37  to produce wrong code if this attribute is used in
38  thumb/thumb-interwork the attribute should only be
39  used for "pure ARM-mode" binaries.
40 */
41 #define INTFUNC __attribute__ ((interrupt("IRQ")))
42 
43 
44 /*
45  NACKEDFUNC
46  gcc will not add any code to a function declared
47  "nacked". The user has to take care to save registers
48  and add the needed code for ISR functions. Some
49  macros for this tasks are provided below.
50 */
51 #define NACKEDFUNC __attribute__((naked))
52 
53 
54 /******************************************************************************
55  *
56  * MACRO Name: ISR_STORE()
57  *
58  * Description:
59  * This MACRO is used upon entry to an ISR with interrupt nesting.
60  * Should be used together with ISR_ENABLE_NEST(). The MACRO
61  * performs the following steps:
62  *
63  * 1 - Save the non-banked registers r0-r12 and lr onto the IRQ stack.
64  *
65  *****************************************************************************/
66 #define ISR_STORE() asm volatile( \
67  "STMDB SP!,{R0-R12,LR}\n" )
68 
69  /******************************************************************************
70  *
71  * MACRO Name: ISR_RESTORE()
72  *
73  * Description:
74  * This MACRO is used upon exit from an ISR with interrupt nesting.
75  * Should be used together with ISR_DISABLE_NEST(). The MACRO
76  * performs the following steps:
77  *
78  * 1 - Load the non-banked registers r0-r12 and lr from the IRQ stack.
79  * 2 - Adjusts resume adress
80  *
81  *****************************************************************************/
82 #define ISR_RESTORE() asm volatile( \
83  "LDMIA SP!,{R0-R12,LR}\n" \
84  "SUBS R15,R14,#0x0004\n" )
85 
86 /******************************************************************************
87  *
88  * MACRO Name: ISR_ENABLE_NEST()
89  *
90  * Description:
91  * This MACRO is used upon entry from an ISR with interrupt nesting.
92  * Should be used after ISR_STORE.
93  *
94  *****************************************************************************/
95 
96 #define ISR_ENABLE_NEST() asm volatile( \
97  "MRS LR, SPSR \n" \
98  "STMFD SP!, {LR} \n" \
99  "MSR CPSR_c, #0x1f \n" \
100  "STMFD SP!, {LR} " )
101 
102 /******************************************************************************
103  *
104  * MACRO Name: ISR_DISABLE_NEST()
105  *
106  * Description:
107  * This MACRO is used upon entry from an ISR with interrupt nesting.
108  * Should be used before ISR_RESTORE.
109  *
110  *****************************************************************************/
111 
112 #define ISR_DISABLE_NEST() asm volatile( \
113  "LDMFD SP!, {LR} \n" \
114  "MSR CPSR_c, #0x92 \n" \
115  "LDMFD SP!, {LR} \n" \
116  "MSR SPSR_cxsf, LR \n" )
117 
118 
119 
120 /*
121  * The following marcos are from the file "armVIC.h" by:
122  *
123  * Copyright 2004, R O SoftWare
124  * No guarantees, warrantees, or promises, implied or otherwise.
125  * May be used for hobby or commercial purposes provided copyright
126  * notice remains intact.
127  *
128  */
129 
130 /******************************************************************************
131  *
132  * MACRO Name: ISR_ENTRY()
133  *
134  * Description:
135  * This MACRO is used upon entry to an ISR. The current version of
136  * the gcc compiler for ARM does not produce correct code for
137  * interrupt routines to operate properly with THUMB code. The MACRO
138  * performs the following steps:
139  *
140  * 1 - Adjust address at which execution should resume after servicing
141  * ISR to compensate for IRQ entry
142  * 2 - Save the non-banked registers r0-r12 and lr onto the IRQ stack.
143  * 3 - Get the status of the interrupted program is in SPSR.
144  * 4 - Push it onto the IRQ stack as well.
145  *
146  *****************************************************************************/
147 #define ISR_ENTRY() asm volatile(" sub lr, lr,#4\n" \
148  " stmfd sp!,{r0-r12,lr}\n" \
149  " mrs r1, spsr\n" \
150  " stmfd sp!,{r1}")
151 
152 /******************************************************************************
153  *
154  * MACRO Name: ISR_EXIT()
155  *
156  * Description:
157  * This MACRO is used to exit an ISR. The current version of the gcc
158  * compiler for ARM does not produce correct code for interrupt
159  * routines to operate properly with THUMB code. The MACRO performs
160  * the following steps:
161  *
162  * 1 - Recover SPSR value from stack
163  * 2 - and restore its value
164  * 3 - Pop the return address & the saved general registers from
165  * the IRQ stack & return
166  *
167  *****************************************************************************/
168 #define ISR_EXIT() asm volatile(" ldmfd sp!,{r1}\n" \
169  " msr spsr_c,r1\n" \
170  " ldmfd sp!,{r0-r12,pc}^")
171 
172 /******************************************************************************
173  *
174  * Function Name: disableIRQ()
175  *
176  * Description:
177  * This function sets the IRQ disable bit in the status register
178  *
179  * Calling Sequence:
180  * void
181  *
182  * Returns:
183  * previous value of CPSR
184  *
185  *****************************************************************************/
186 unsigned disableIRQ(void);
187 
188 /******************************************************************************
189  *
190  * Function Name: enableIRQ()
191  *
192  * Description:
193  * This function clears the IRQ disable bit in the status register
194  *
195  * Calling Sequence:
196  * void
197  *
198  * Returns:
199  * previous value of CPSR
200  *
201  *****************************************************************************/
202 unsigned enableIRQ(void);
203 
204 /******************************************************************************
205  *
206  * Function Name: restoreIRQ()
207  *
208  * Description:
209  * This function restores the IRQ disable bit in the status register
210  * to the value contained within passed oldCPSR
211  *
212  * Calling Sequence:
213  * void
214  *
215  * Returns:
216  * previous value of CPSR
217  *
218  *****************************************************************************/
219 unsigned restoreIRQ(unsigned oldCPSR);
220 
221 /******************************************************************************
222  *
223  * Function Name: disableFIQ()
224  *
225  * Description:
226  * This function sets the FIQ disable bit in the status register
227  *
228  * Calling Sequence:
229  * void
230  *
231  * Returns:
232  * previous value of CPSR
233  *
234  *****************************************************************************/
235 unsigned disableFIQ(void);
236 
237 /******************************************************************************
238  *
239  * Function Name: enableFIQ()
240  *
241  * Description:
242  * This function clears the FIQ disable bit in the status register
243  *
244  * Calling Sequence:
245  * void
246  *
247  * Returns:
248  * previous value of CPSR
249  *
250  *****************************************************************************/
251 unsigned enableFIQ(void);
252 
253 /******************************************************************************
254  *
255  * Function Name: restoreFIQ()
256  *
257  * Description:
258  * This function restores the FIQ disable bit in the status register
259  * to the value contained within passed oldCPSR
260  *
261  * Calling Sequence:
262  * void
263  *
264  * Returns:
265  * previous value of CPSR
266  *
267  *****************************************************************************/
268 unsigned restoreFIQ(unsigned oldCPSR);
269 
270 
271 #endif
272