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