]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_LM3S811_GCC/hw_include/interrupt.c
Add FreeRTOS-Plus directory.
[freertos] / FreeRTOS / Demo / CORTEX_LM3S811_GCC / hw_include / interrupt.c
1 //*****************************************************************************\r
2 //\r
3 // interrupt.c - Driver for the NVIC Interrupt Controller.\r
4 //\r
5 // Copyright (c) 2005,2006 Luminary Micro, Inc.  All rights reserved.\r
6 //\r
7 // Software License Agreement\r
8 //\r
9 // Luminary Micro, Inc. (LMI) is supplying this software for use solely and\r
10 // exclusively on LMI's Stellaris Family of microcontroller products.\r
11 //\r
12 // The software is owned by LMI and/or its suppliers, and is protected under\r
13 // applicable copyright laws.  All rights are reserved.  Any use in violation\r
14 // of the foregoing restrictions may subject the user to criminal sanctions\r
15 // under applicable laws, as well as to civil liability for the breach of the\r
16 // terms and conditions of this license.\r
17 //\r
18 // THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED\r
19 // OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF\r
20 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.\r
21 // LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR\r
22 // CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.\r
23 //\r
24 // This is part of revision 991 of the Stellaris Driver Library.\r
25 //\r
26 //*****************************************************************************\r
27 \r
28 //*****************************************************************************\r
29 //\r
30 //! \addtogroup interrupt_api\r
31 //! @{\r
32 //\r
33 //*****************************************************************************\r
34 \r
35 #include "../hw_ints.h"\r
36 #include "../hw_nvic.h"\r
37 #include "../hw_types.h"\r
38 #include "cpu.h"\r
39 #include "debug.h"\r
40 #include "interrupt.h"\r
41 \r
42 //*****************************************************************************\r
43 //\r
44 // This is a mapping between priority grouping encodings and the number of\r
45 // preemption priority bits.\r
46 //\r
47 //*****************************************************************************\r
48 #if defined(GROUP_pulpriority) || defined(BUILD_ALL)\r
49 const unsigned long g_pulPriority[] =\r
50 {\r
51     NVIC_APINT_PRIGROUP_0_8, NVIC_APINT_PRIGROUP_1_7, NVIC_APINT_PRIGROUP_2_6,\r
52     NVIC_APINT_PRIGROUP_3_5, NVIC_APINT_PRIGROUP_4_4, NVIC_APINT_PRIGROUP_5_3,\r
53     NVIC_APINT_PRIGROUP_6_2, NVIC_APINT_PRIGROUP_7_1\r
54 };\r
55 #else\r
56 extern const unsigned long g_pulPriority[];\r
57 #endif\r
58 \r
59 //*****************************************************************************\r
60 //\r
61 // This is a mapping between interrupt number and the register that contains\r
62 // the priority encoding for that interrupt.\r
63 //\r
64 //*****************************************************************************\r
65 #if defined(GROUP_pulregs) || defined(BUILD_ALL)\r
66 const unsigned long g_pulRegs[12] =\r
67 {\r
68     0, NVIC_SYS_PRI1, NVIC_SYS_PRI2, NVIC_SYS_PRI3, NVIC_PRI0, NVIC_PRI1,\r
69     NVIC_PRI2, NVIC_PRI3, NVIC_PRI4, NVIC_PRI5, NVIC_PRI6, NVIC_PRI7\r
70 };\r
71 #else\r
72 extern const unsigned long g_pulRegs[12];\r
73 #endif\r
74 \r
75 //*****************************************************************************\r
76 //\r
77 //! \internal\r
78 //! The default interrupt handler.\r
79 //!\r
80 //! This is the default interrupt handler for all interrupts.  It simply loops\r
81 //! forever so that the system state is preserved for observation by a\r
82 //! debugger.  Since interrupts should be disabled before unregistering the\r
83 //! corresponding handler, this should never be called.\r
84 //!\r
85 //! \return None.\r
86 //\r
87 //*****************************************************************************\r
88 #if defined(GROUP_defaulthandler) || defined(BUILD_ALL)\r
89 void\r
90 IntDefaultHandler(void)\r
91 {\r
92     //\r
93     // Go into an infinite loop.\r
94     //\r
95     while(1)\r
96     {\r
97     }\r
98 }\r
99 #else\r
100 extern void IntDefaultHandler(void);\r
101 #endif\r
102 \r
103 //*****************************************************************************\r
104 //\r
105 // The processor vector table.\r
106 //\r
107 // This contains a list of the handlers for the various interrupt sources in\r
108 // the system.  The layout of this list is defined by the hardware; assertion\r
109 // of an interrupt causes the processor to start executing directly at the\r
110 // address given in the corresponding location in this list.\r
111 //\r
112 //*****************************************************************************\r
113 #if defined(GROUP_vtable) || defined(BUILD_ALL)\r
114 #ifdef ewarm\r
115 __no_init void (*g_pfnRAMVectors[NUM_INTERRUPTS])(void) @ "VTABLE";\r
116 #else\r
117 __attribute__((section("vtable")))\r
118 void (*g_pfnRAMVectors[NUM_INTERRUPTS])(void);\r
119 #endif\r
120 #else\r
121 extern void (*g_pfnRAMVectors[NUM_INTERRUPTS])(void);\r
122 #endif\r
123 \r
124 //*****************************************************************************\r
125 //\r
126 //! Enables the processor interrupt.\r
127 //!\r
128 //! Allows the processor to respond to interrupts.  This does not affect the\r
129 //! set of interrupts enabled in the interrupt controller; it just gates the\r
130 //! single interrupt from the controller to the processor.\r
131 //!\r
132 //! \return None.\r
133 //\r
134 //*****************************************************************************\r
135 #if defined(GROUP_masterenable) || defined(BUILD_ALL) || defined(DOXYGEN)\r
136 void\r
137 IntMasterEnable(void)\r
138 {\r
139     //\r
140     // Enable processor interrupts.\r
141     //\r
142     CPUcpsie();\r
143 }\r
144 #endif\r
145 \r
146 //*****************************************************************************\r
147 //\r
148 //! Disables the processor interrupt.\r
149 //!\r
150 //! Prevents the processor from receiving interrupts.  This does not affect the\r
151 //! set of interrupts enabled in the interrupt controller; it just gates the\r
152 //! single interrupt from the controller to the processor.\r
153 //!\r
154 //! \return None.\r
155 //\r
156 //*****************************************************************************\r
157 #if defined(GROUP_masterdisable) || defined(BUILD_ALL) || defined(DOXYGEN)\r
158 void\r
159 IntMasterDisable(void)\r
160 {\r
161     //\r
162     // Disable processor interrupts.\r
163     //\r
164     CPUcpsid();\r
165 }\r
166 #endif\r
167 \r
168 //*****************************************************************************\r
169 //\r
170 //! Registers a function to be called when an interrupt occurs.\r
171 //!\r
172 //! \param ulInterrupt specifies the interrupt in question.\r
173 //! \param pfnHandler is a pointer to the function to be called.\r
174 //!\r
175 //! This function is used to specify the handler function to be called when the\r
176 //! given interrupt is asserted to the processor.  When the interrupt occurs,\r
177 //! if it is enabled (via IntEnable()), the handler function will be called in\r
178 //! interrupt context.  Since the handler function can preempt other code, care\r
179 //! must be taken to protect memory or peripherals that are accessed by the\r
180 //! handler and other non-handler code.\r
181 //!\r
182 //! \note The use of this function (directly or indirectly via a peripheral\r
183 //! driver interrupt register function) moves the interrupt vector table from\r
184 //! flash to SRAM.  Therefore, care must be taken when linking the application\r
185 //! to ensure that the SRAM vector table is located at the beginning of SRAM;\r
186 //! otherwise NVIC will not look in the correct portion of memory for the\r
187 //! vector table (it requires the vector table be on a 1 kB memory alignment).\r
188 //! Normally, the SRAM vector table is so placed via the use of linker scripts;\r
189 //! some tool chains, such as the evaluation version of RV-MDK, do not support\r
190 //! linker scripts and therefore will not produce a valid executable.  See the\r
191 //! discussion of compile-time versus run-time interrupt handler registration\r
192 //! in the introduction to this chapter.\r
193 //!\r
194 //! \return None.\r
195 //\r
196 //*****************************************************************************\r
197 #if defined(GROUP_register) || defined(BUILD_ALL) || defined(DOXYGEN)\r
198 void\r
199 IntRegister(unsigned long ulInterrupt, void (*pfnHandler)(void))\r
200 {\r
201     unsigned long ulIdx;\r
202 \r
203     //\r
204     // Check the arguments.\r
205     //\r
206     ASSERT(ulInterrupt < NUM_INTERRUPTS);\r
207 \r
208     //\r
209     // Make sure that the RAM vector table is correctly aligned.\r
210     //\r
211     ASSERT(((unsigned long)g_pfnRAMVectors & 0x000003ff) == 0);\r
212 \r
213     //\r
214     // See if the RAM vector table has been initialized.\r
215     //\r
216     if(HWREG(NVIC_VTABLE) != (unsigned long)g_pfnRAMVectors)\r
217     {\r
218         //\r
219         // Copy the vector table from the beginning of FLASH to the RAM vector\r
220         // table.\r
221         //\r
222         for(ulIdx = 0; ulIdx < NUM_INTERRUPTS; ulIdx++)\r
223         {\r
224             g_pfnRAMVectors[ulIdx] = (void (*)(void))HWREG(ulIdx * 4);\r
225         }\r
226 \r
227         //\r
228         // Point NVIC at the RAM vector table.\r
229         //\r
230         HWREG(NVIC_VTABLE) = (unsigned long)g_pfnRAMVectors;\r
231     }\r
232 \r
233     //\r
234     // Save the interrupt handler.\r
235     //\r
236     g_pfnRAMVectors[ulInterrupt] = pfnHandler;\r
237 }\r
238 #endif\r
239 \r
240 //*****************************************************************************\r
241 //\r
242 //! Unregisters the function to be called when an interrupt occurs.\r
243 //!\r
244 //! \param ulInterrupt specifies the interrupt in question.\r
245 //!\r
246 //! This function is used to indicate that no handler should be called when the\r
247 //! given interrupt is asserted to the processor.  The interrupt source will be\r
248 //! automatically disabled (via IntDisable()) if necessary.\r
249 //!\r
250 //! \sa IntRegister() for important information about registering interrupt\r
251 //! handlers.\r
252 //!\r
253 //! \return None.\r
254 //\r
255 //*****************************************************************************\r
256 #if defined(GROUP_unregister) || defined(BUILD_ALL) || defined(DOXYGEN)\r
257 void\r
258 IntUnregister(unsigned long ulInterrupt)\r
259 {\r
260     //\r
261     // Check the arguments.\r
262     //\r
263     ASSERT(ulInterrupt < NUM_INTERRUPTS);\r
264 \r
265     //\r
266     // Reset the interrupt handler.\r
267     //\r
268     g_pfnRAMVectors[ulInterrupt] = IntDefaultHandler;\r
269 }\r
270 #endif\r
271 \r
272 //*****************************************************************************\r
273 //\r
274 //! Sets the priority grouping of the interrupt controller.\r
275 //!\r
276 //! \param ulBits specifies the number of bits of preemptable priority.\r
277 //!\r
278 //! This function specifies the split between preemptable priority levels and\r
279 //! subpriority levels in the interrupt priority specification.  The range of\r
280 //! the grouping values are dependent upon the hardware implementation; on\r
281 //! the Stellaris family it can range from 0 to 3.\r
282 //!\r
283 //! \return None.\r
284 //\r
285 //*****************************************************************************\r
286 #if defined(GROUP_prioritygroupingset) || defined(BUILD_ALL) || \\r
287     defined(DOXYGEN)\r
288 void\r
289 IntPriorityGroupingSet(unsigned long ulBits)\r
290 {\r
291     //\r
292     // Check the arguments.\r
293     //\r
294     ASSERT(ulBits < NUM_PRIORITY_BITS);\r
295 \r
296     //\r
297     // Set the priority grouping.\r
298     //\r
299     HWREG(NVIC_APINT) = NVIC_APINT_VECTKEY | g_pulPriority[ulBits];\r
300 }\r
301 #endif\r
302 \r
303 //*****************************************************************************\r
304 //\r
305 //! Gets the priority grouping of the interrupt controller.\r
306 //!\r
307 //! This function returns the split between preemptable priority levels and\r
308 //! subpriority levels in the interrupt priority specification.\r
309 //!\r
310 //! \return The number of bits of preemptable priority.\r
311 //\r
312 //*****************************************************************************\r
313 #if defined(GROUP_prioritygroupingget) || defined(BUILD_ALL) || \\r
314     defined(DOXYGEN)\r
315 unsigned long\r
316 IntPriorityGroupingGet(void)\r
317 {\r
318     unsigned long ulLoop, ulValue;\r
319 \r
320     //\r
321     // Read the priority grouping.\r
322     //\r
323     ulValue = HWREG(NVIC_APINT) & NVIC_APINT_PRIGROUP_M;\r
324 \r
325     //\r
326     // Loop through the priority grouping values.\r
327     //\r
328     for(ulLoop = 0; ulLoop < 8; ulLoop++)\r
329     {\r
330         //\r
331         // Stop looping if this value matches.\r
332         //\r
333         if(ulValue == g_pulPriority[ulLoop])\r
334         {\r
335             break;\r
336         }\r
337     }\r
338 \r
339     //\r
340     // Return the number of priority bits.\r
341     //\r
342     return(ulLoop);\r
343 }\r
344 #endif\r
345 \r
346 //*****************************************************************************\r
347 //\r
348 //! Sets the priority of an interrupt.\r
349 //!\r
350 //! \param ulInterrupt specifies the interrupt in question.\r
351 //! \param ucPriority specifies the priority of the interrupt.\r
352 //!\r
353 //! This function is used to set the priority of an interrupt.  When multiple\r
354 //! interrupts are asserted simultaneously, the ones with the highest priority\r
355 //! are processed before the lower priority interrupts.  Smaller numbers\r
356 //! correspond to higher interrupt priorities; priority 0 is the highest\r
357 //! interrupt priority.\r
358 //!\r
359 //! The hardware priority mechanism will only look at the upper N bits of the\r
360 //! priority level (where N is 3 for the Stellaris family), so any\r
361 //! prioritization must be performed in those bits.  The remaining bits can be\r
362 //! used to sub-prioritize the interrupt sources, and may be used by the\r
363 //! hardware priority mechanism on a future part.  This arrangement allows\r
364 //! priorities to migrate to different NVIC implementations without changing\r
365 //! the gross prioritization of the interrupts.\r
366 //!\r
367 //! \return None.\r
368 //\r
369 //*****************************************************************************\r
370 #if defined(GROUP_priorityset) || defined(BUILD_ALL) || defined(DOXYGEN)\r
371 void\r
372 IntPrioritySet(unsigned long ulInterrupt, unsigned char ucPriority)\r
373 {\r
374     unsigned long ulTemp;\r
375 \r
376     //\r
377     // Check the arguments.\r
378     //\r
379     ASSERT((ulInterrupt >= 4) && (ulInterrupt < NUM_INTERRUPTS));\r
380 \r
381     //\r
382     // Set the interrupt priority.\r
383     //\r
384     ulTemp = HWREG(g_pulRegs[ulInterrupt >> 2]);\r
385     ulTemp &= ~(0xFF << (8 * (ulInterrupt & 3)));\r
386     ulTemp |= ucPriority << (8 * (ulInterrupt & 3));\r
387     HWREG(g_pulRegs[ulInterrupt >> 2]) = ulTemp;\r
388 }\r
389 #endif\r
390 \r
391 //*****************************************************************************\r
392 //\r
393 //! Gets the priority of an interrupt.\r
394 //!\r
395 //! \param ulInterrupt specifies the interrupt in question.\r
396 //!\r
397 //! This function gets the priority of an interrupt.  See IntPrioritySet() for\r
398 //! a definition of the priority value.\r
399 //!\r
400 //! \return Returns the interrupt priority, or -1 if an invalid interrupt was\r
401 //! specified.\r
402 //\r
403 //*****************************************************************************\r
404 #if defined(GROUP_priorityget) || defined(BUILD_ALL) || defined(DOXYGEN)\r
405 long\r
406 IntPriorityGet(unsigned long ulInterrupt)\r
407 {\r
408     //\r
409     // Check the arguments.\r
410     //\r
411     ASSERT((ulInterrupt >= 4) && (ulInterrupt < NUM_INTERRUPTS));\r
412 \r
413     //\r
414     // Return the interrupt priority.\r
415     //\r
416     return((HWREG(g_pulRegs[ulInterrupt >> 2]) >> (8 * (ulInterrupt & 3))) &\r
417            0xFF);\r
418 }\r
419 #endif\r
420 \r
421 //*****************************************************************************\r
422 //\r
423 //! Enables an interrupt.\r
424 //!\r
425 //! \param ulInterrupt specifies the interrupt to be enabled.\r
426 //!\r
427 //! The specified interrupt is enabled in the interrupt controller.  Other\r
428 //! enables for the interrupt (such as at the peripheral level) are unaffected\r
429 //! by this function.\r
430 //!\r
431 //! \return None.\r
432 //\r
433 //*****************************************************************************\r
434 #if defined(GROUP_enable) || defined(BUILD_ALL) || defined(DOXYGEN)\r
435 void\r
436 IntEnable(unsigned long ulInterrupt)\r
437 {\r
438     //\r
439     // Check the arguments.\r
440     //\r
441     ASSERT(ulInterrupt < NUM_INTERRUPTS);\r
442 \r
443     //\r
444     // Determine the interrupt to enable.\r
445     //\r
446     if(ulInterrupt == FAULT_MPU)\r
447     {\r
448         //\r
449         // Enable the MemManage interrupt.\r
450         //\r
451         HWREG(NVIC_SYS_HND_CTRL) |= NVIC_SYS_HND_CTRL_MEM;\r
452     }\r
453     else if(ulInterrupt == FAULT_BUS)\r
454     {\r
455         //\r
456         // Enable the bus fault interrupt.\r
457         //\r
458         HWREG(NVIC_SYS_HND_CTRL) |= NVIC_SYS_HND_CTRL_BUS;\r
459     }\r
460     else if(ulInterrupt == FAULT_USAGE)\r
461     {\r
462         //\r
463         // Enable the usage fault interrupt.\r
464         //\r
465         HWREG(NVIC_SYS_HND_CTRL) |= NVIC_SYS_HND_CTRL_USAGE;\r
466     }\r
467     else if(ulInterrupt == FAULT_SYSTICK)\r
468     {\r
469         //\r
470         // Enable the System Tick interrupt.\r
471         //\r
472         HWREG(NVIC_ST_CTRL) |= NVIC_ST_CTRL_INTEN;\r
473     }\r
474     else if(ulInterrupt >= INT_GPIOA)\r
475     {\r
476         //\r
477         // Enable the general interrupt.\r
478         //\r
479         HWREG(NVIC_EN0) = 1 << (ulInterrupt - INT_GPIOA);\r
480     }\r
481 }\r
482 #endif\r
483 \r
484 //*****************************************************************************\r
485 //\r
486 //! Disables an interrupt.\r
487 //!\r
488 //! \param ulInterrupt specifies the interrupt to be disabled.\r
489 //!\r
490 //! The specified interrupt is disabled in the interrupt controller.  Other\r
491 //! enables for the interrupt (such as at the peripheral level) are unaffected\r
492 //! by this function.\r
493 //!\r
494 //! \return None.\r
495 //\r
496 //*****************************************************************************\r
497 #if defined(GROUP_disable) || defined(BUILD_ALL) || defined(DOXYGEN)\r
498 void\r
499 IntDisable(unsigned long ulInterrupt)\r
500 {\r
501     //\r
502     // Check the arguments.\r
503     //\r
504     ASSERT(ulInterrupt < NUM_INTERRUPTS);\r
505 \r
506     //\r
507     // Determine the interrupt to disable.\r
508     //\r
509     if(ulInterrupt == FAULT_MPU)\r
510     {\r
511         //\r
512         // Disable the MemManage interrupt.\r
513         //\r
514         HWREG(NVIC_SYS_HND_CTRL) &= ~(NVIC_SYS_HND_CTRL_MEM);\r
515     }\r
516     else if(ulInterrupt == FAULT_BUS)\r
517     {\r
518         //\r
519         // Disable the bus fault interrupt.\r
520         //\r
521         HWREG(NVIC_SYS_HND_CTRL) &= ~(NVIC_SYS_HND_CTRL_BUS);\r
522     }\r
523     else if(ulInterrupt == FAULT_USAGE)\r
524     {\r
525         //\r
526         // Disable the usage fault interrupt.\r
527         //\r
528         HWREG(NVIC_SYS_HND_CTRL) &= ~(NVIC_SYS_HND_CTRL_USAGE);\r
529     }\r
530     else if(ulInterrupt == FAULT_SYSTICK)\r
531     {\r
532         //\r
533         // Disable the System Tick interrupt.\r
534         //\r
535         HWREG(NVIC_ST_CTRL) &= ~(NVIC_ST_CTRL_INTEN);\r
536     }\r
537     else if(ulInterrupt >= INT_GPIOA)\r
538     {\r
539         //\r
540         // Disable the general interrupt.\r
541         //\r
542         HWREG(NVIC_DIS0) = 1 << (ulInterrupt - INT_GPIOA);\r
543     }\r
544 }\r
545 #endif\r
546 \r
547 //*****************************************************************************\r
548 //\r
549 // Close the Doxygen group.\r
550 //! @}\r
551 //\r
552 //*****************************************************************************\r