]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_M4F_MSP432_LaunchPad_IAR_CCS_Keil/driverlib/interrupt.c
commit 9f316c246baafa15c542a5aea81a94f26e3d6507
[freertos] / FreeRTOS / Demo / CORTEX_M4F_MSP432_LaunchPad_IAR_CCS_Keil / driverlib / interrupt.c
1 /*
2  * -------------------------------------------
3  *    MSP432 DriverLib - v3_10_00_09 
4  * -------------------------------------------
5  *
6  * --COPYRIGHT--,BSD,BSD
7  * Copyright (c) 2014, Texas Instruments Incorporated
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  *
14  * *  Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  *
17  * *  Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  *
21  * *  Neither the name of Texas Instruments Incorporated nor the names of
22  *    its contributors may be used to endorse or promote products derived
23  *    from this software without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
27  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
29  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
32  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
33  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
34  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
35  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36  * --/COPYRIGHT--*/
37 /* Standard Includes */
38 #include <stdint.h>
39
40 /* DriverLib Includes */
41 #include <debug.h>
42 #include <cpu.h>
43 #include <interrupt.h>
44 #include <hw_memmap.h>
45
46 //*****************************************************************************
47 //
48 // This is a mapping between priority grouping encodings and the number of
49 // preemption priority bits.
50 //
51 //*****************************************************************************
52 static const uint32_t g_pulPriority[] =
53 { NVIC_APINT_PRIGROUP_0_8, NVIC_APINT_PRIGROUP_1_7, NVIC_APINT_PRIGROUP_2_6,
54 NVIC_APINT_PRIGROUP_3_5, NVIC_APINT_PRIGROUP_4_4,
55 NVIC_APINT_PRIGROUP_5_3, NVIC_APINT_PRIGROUP_6_2,
56 NVIC_APINT_PRIGROUP_7_1 };
57
58 //*****************************************************************************
59 //
60 // This is a mapping between interrupt number and the register that contains
61 // the priority encoding for that interrupt.
62 //
63 //*****************************************************************************
64 static const uint32_t g_pulRegs[] =
65 { 0, NVIC_SYS_PRI1_R, NVIC_SYS_PRI2_R, NVIC_SYS_PRI3_R, NVIC_PRI0_R,
66 NVIC_PRI1_R, NVIC_PRI2_R, NVIC_PRI3_R, NVIC_PRI4_R, NVIC_PRI5_R,
67 NVIC_PRI6_R, NVIC_PRI7_R, NVIC_PRI8_R, NVIC_PRI9_R, NVIC_PRI10_R,
68 NVIC_PRI11_R, NVIC_PRI12_R, NVIC_PRI13_R, NVIC_PRI14_R, NVIC_PRI15_R };
69
70 //*****************************************************************************
71 //
72 // This is a mapping between interrupt number (for the peripheral interrupts
73 // only) and the register that contains the interrupt enable for that
74 // interrupt.
75 //
76 //*****************************************************************************
77 static const uint32_t g_pulEnRegs[] =
78 { NVIC_EN0_R, NVIC_EN1_R };
79
80 //*****************************************************************************
81 //
82 // This is a mapping between interrupt number (for the peripheral interrupts
83 // only) and the register that contains the interrupt disable for that
84 // interrupt.
85 //
86 //*****************************************************************************
87 static const uint32_t g_pulDisRegs[] =
88 { NVIC_DIS0_R, NVIC_DIS1_R };
89
90 //*****************************************************************************
91 //
92 // This is a mapping between interrupt number (for the peripheral interrupts
93 // only) and the register that contains the interrupt pend for that interrupt.
94 //
95 //*****************************************************************************
96 static const uint32_t g_pulPendRegs[] =
97 { NVIC_PEND0_R, NVIC_PEND1_R };
98
99 //*****************************************************************************
100 //
101 // This is a mapping between interrupt number (for the peripheral interrupts
102 // only) and the register that contains the interrupt unpend for that
103 // interrupt.
104 //
105 //*****************************************************************************
106 static const uint32_t g_pulUnpendRegs[] =
107 { NVIC_UNPEND0_R, NVIC_UNPEND1_R };
108
109 //*****************************************************************************
110 //
111 //! \internal
112 //! The default interrupt handler.
113 //!
114 //! This is the default interrupt handler for all interrupts.  It simply loops
115 //! forever so that the system state is preserved for observation by a
116 //! debugger.  Since interrupts should be disabled before unregistering the
117 //! corresponding handler, this should never be called.
118 //!
119 //! \return None.
120 //
121 //*****************************************************************************
122 static void IntDefaultHandler(void)
123 {
124     //
125     // Go into an infinite loop.
126     //
127     while (1)
128     {
129     }
130 }
131
132 //*****************************************************************************
133 //
134 // The processor vector table.
135 //
136 // This contains a list of the handlers for the various interrupt sources in
137 // the system.  The layout of this list is defined by the hardware; assertion
138 // of an interrupt causes the processor to start executing directly at the
139 // address given in the corresponding location in this list.
140 //
141 //*****************************************************************************
142 #if defined(ewarm)
143 #pragma data_alignment=1024
144 static __no_init void (*g_pfnRAMVectors[NUM_INTERRUPTS+1])(void) @ "VTABLE";
145 #elif defined(ccs)
146 #pragma DATA_ALIGN(g_pfnRAMVectors, 1024)
147 #pragma DATA_SECTION(g_pfnRAMVectors, ".vtable")
148 void (*g_pfnRAMVectors[NUM_INTERRUPTS + 1])(void);
149 #else
150 static __attribute__((section("vtable")))
151 void (*g_pfnRAMVectors[NUM_INTERRUPTS+1])(void) __attribute__((aligned(1024)));
152 #endif
153
154 bool Interrupt_enableMaster(void)
155 {
156     //
157     // Enable processor interrupts.
158     //
159     return (CPU_cpsie());
160 }
161
162 bool Interrupt_disableMaster(void)
163 {
164     //
165     // Disable processor interrupts.
166     //
167     return (CPU_cpsid());
168 }
169
170 void Interrupt_registerInterrupt(uint32_t interruptNumber,
171         void (*intHandler)(void))
172 {
173     uint32_t ulIdx, ulValue;
174
175     //
176     // Check the arguments.
177     //
178     ASSERT(interruptNumber < (NUM_INTERRUPTS+1));
179
180     //
181     // Make sure that the RAM vector table is correctly aligned.
182     //
183     ASSERT(((uint32_t) g_pfnRAMVectors & 0x000000ff) == 0);
184
185     //
186     // See if the RAM vector table has been initialized.
187     //
188     if (SCB->VTOR != (uint32_t) g_pfnRAMVectors)
189     {
190         //
191         // Copy the vector table from the beginning of FLASH to the RAM vector
192         // table.
193         //
194         ulValue = SCB->VTOR;
195         for (ulIdx = 0; ulIdx < (NUM_INTERRUPTS + 1); ulIdx++)
196         {
197             g_pfnRAMVectors[ulIdx] = (void (*)(void)) HWREG32(
198                     (ulIdx * 4) + ulValue);
199         }
200
201         //
202         // Point the NVIC at the RAM vector table.
203         //
204         SCB->VTOR = (uint32_t) g_pfnRAMVectors;
205     }
206
207     //
208     // Save the interrupt handler.
209     //
210     g_pfnRAMVectors[interruptNumber] = intHandler;
211 }
212
213 void Interrupt_unregisterInterrupt(uint32_t interruptNumber)
214 {
215     //
216     // Check the arguments.
217     //
218     ASSERT(interruptNumber < (NUM_INTERRUPTS+1));
219
220     //
221     // Reset the interrupt handler.
222     //
223     g_pfnRAMVectors[interruptNumber] = IntDefaultHandler;
224 }
225
226 void Interrupt_setPriorityGrouping(uint32_t bits)
227 {
228     //
229     // Check the arguments.
230     //
231     ASSERT(bits < NUM_PRIORITY);
232
233     //
234     // Set the priority grouping.
235     //
236     SCB->AIRCR = SCB_AIRCR_VECTKEY_Msk | g_pulPriority[bits];
237 }
238
239 uint32_t Interrupt_getPriorityGrouping(void)
240 {
241     uint32_t ulLoop, ulValue;
242
243     //
244     // Read the priority grouping.
245     //
246     ulValue = SCB->AIRCR & NVIC_APINT_PRIGROUP_M;
247
248     //
249     // Loop through the priority grouping values.
250     //
251     for (ulLoop = 0; ulLoop < NUM_PRIORITY; ulLoop++)
252     {
253         //
254         // Stop looping if this value matches.
255         //
256         if (ulValue == g_pulPriority[ulLoop])
257         {
258             break;
259         }
260     }
261
262     //
263     // Return the number of priority bits.
264     //
265     return (ulLoop);
266 }
267
268 void Interrupt_setPriority(uint32_t interruptNumber, uint8_t priority)
269 {
270     uint32_t ulTemp;
271
272     //
273     // Check the arguments.
274     //
275     ASSERT((interruptNumber >= 4) && (interruptNumber < (NUM_INTERRUPTS+1)));
276
277     //
278     // Set the interrupt priority.
279     //
280     ulTemp = HWREG32(g_pulRegs[interruptNumber >> 2]);
281     ulTemp &= ~(0xFF << (8 * (interruptNumber & 3)));
282     ulTemp |= priority << (8 * (interruptNumber & 3));
283     HWREG32 (g_pulRegs[interruptNumber >> 2]) = ulTemp;
284 }
285
286 uint8_t Interrupt_getPriority(uint32_t interruptNumber)
287 {
288     //
289     // Check the arguments.
290     //
291     ASSERT((interruptNumber >= 4) && (interruptNumber < (NUM_INTERRUPTS+1)));
292
293     //
294     // Return the interrupt priority.
295     //
296     return ((HWREG32(g_pulRegs[interruptNumber >> 2])
297             >> (8 * (interruptNumber & 3))) & 0xFF);
298 }
299
300 void Interrupt_enableInterrupt(uint32_t interruptNumber)
301 {
302     //
303     // Check the arguments.
304     //
305     ASSERT(interruptNumber < (NUM_INTERRUPTS+1));
306
307     //
308     // Determine the interrupt to enable.
309     //
310     if (interruptNumber == FAULT_MPU)
311     {
312         //
313         // Enable the MemManage interrupt.
314         //
315         SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
316     } else if (interruptNumber == FAULT_BUS)
317     {
318         //
319         // Enable the bus fault interrupt.
320         //
321         SCB->SHCSR |= SCB_SHCSR_BUSFAULTENA_Msk;
322     } else if (interruptNumber == FAULT_USAGE)
323     {
324         //
325         // Enable the usage fault interrupt.
326         //
327         SCB->SHCSR |= SCB_SHCSR_USGFAULTENA_Msk;
328     } else if (interruptNumber == FAULT_SYSTICK)
329     {
330         //
331         // Enable the System Tick interrupt.
332         //
333         SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
334     } else if (interruptNumber >= 16)
335     {
336         //
337         // Enable the general interrupt.
338         //
339         HWREG32 (g_pulEnRegs[(interruptNumber - 16) / 32]) = 1
340                 << ((interruptNumber - 16) & 31);
341     }
342 }
343
344 void Interrupt_disableInterrupt(uint32_t interruptNumber)
345 {
346     //
347     // Check the arguments.
348     //
349     ASSERT(interruptNumber < (NUM_INTERRUPTS+1));
350
351     //
352     // Determine the interrupt to disable.
353     //
354     if (interruptNumber == FAULT_MPU)
355     {
356         //
357         // Disable the MemManage interrupt.
358         //
359         SCB->SHCSR &= ~(SCB_SHCSR_MEMFAULTENA_Msk);
360     } else if (interruptNumber == FAULT_BUS)
361     {
362         //
363         // Disable the bus fault interrupt.
364         //
365         SCB->SHCSR &= ~(SCB_SHCSR_BUSFAULTENA_Msk);
366     } else if (interruptNumber == FAULT_USAGE)
367     {
368         //
369         // Disable the usage fault interrupt.
370         //
371         SCB->SHCSR &= ~(SCB_SHCSR_USGFAULTENA_Msk);
372     } else if (interruptNumber == FAULT_SYSTICK)
373     {
374         //
375         // Disable the System Tick interrupt.
376         //
377         SysTick->CTRL &= ~(SysTick_CTRL_ENABLE_Msk);
378     } else if (interruptNumber >= 16)
379     {
380         //
381         // Disable the general interrupt.
382         //
383         HWREG32 (g_pulDisRegs[(interruptNumber - 16) / 32]) = 1
384                 << ((interruptNumber - 16) & 31);
385     }
386 }
387
388 bool Interrupt_isEnabled(uint32_t interruptNumber)
389 {
390     uint32_t ulRet;
391
392     //
393     // Check the arguments.
394     //
395     ASSERT(interruptNumber < (NUM_INTERRUPTS+1));
396
397     //
398     // Initialize the return value.
399     //
400     ulRet = 0;
401
402     //
403     // Determine the interrupt to disable.
404     //
405     if (interruptNumber == FAULT_MPU)
406     {
407         //
408         // Check the MemManage interrupt.
409         //
410         ulRet = SCB->SHCSR & SCB_SHCSR_MEMFAULTENA_Msk;
411     } else if (interruptNumber == FAULT_BUS)
412     {
413         //
414         // Check the bus fault interrupt.
415         //
416         ulRet = SCB->SHCSR & SCB_SHCSR_BUSFAULTENA_Msk;
417     } else if (interruptNumber == FAULT_USAGE)
418     {
419         //
420         // Check the usage fault interrupt.
421         //
422         ulRet = SCB->SHCSR & SCB_SHCSR_USGFAULTENA_Msk;
423     } else if (interruptNumber == FAULT_SYSTICK)
424     {
425         //
426         // Check the System Tick interrupt.
427         //
428         ulRet = SysTick->CTRL & SysTick_CTRL_ENABLE_Msk;
429     } else if (interruptNumber >= 16)
430     {
431         //
432         // Check the general interrupt.
433         //
434         ulRet = HWREG32(g_pulEnRegs[(interruptNumber - 16) / 32])
435                 & (1 << ((interruptNumber - 16) & 31));
436     }
437     return (ulRet);
438 }
439
440 void Interrupt_pendInterrupt(uint32_t interruptNumber)
441 {
442     //
443     // Check the arguments.
444     //
445     ASSERT(interruptNumber < (NUM_INTERRUPTS+1));
446
447     //
448     // Determine the interrupt to pend.
449     //
450     if (interruptNumber == FAULT_NMI)
451     {
452         //
453         // Pend the NMI interrupt.
454         //
455         SCB->ICSR |= SCB_ICSR_NMIPENDSET_Msk;
456     } else if (interruptNumber == FAULT_PENDSV)
457     {
458         //
459         // Pend the PendSV interrupt.
460         //
461         SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;
462     } else if (interruptNumber == FAULT_SYSTICK)
463     {
464         //
465         // Pend the SysTick interrupt.
466         //
467         SCB->ICSR |= SCB_ICSR_PENDSTSET_Msk;
468     } else if (interruptNumber >= 16)
469     {
470         //
471         // Pend the general interrupt.
472         //
473         HWREG32 (g_pulPendRegs[(interruptNumber - 16) / 32]) = 1
474                 << ((interruptNumber - 16) & 31);
475     }
476 }
477
478 void Interrupt_unpendInterrupt(uint32_t interruptNumber)
479 {
480     //
481     // Check the arguments.
482     //
483     ASSERT(interruptNumber < (NUM_INTERRUPTS+1));
484
485     //
486     // Determine the interrupt to unpend.
487     //
488     if (interruptNumber == FAULT_PENDSV)
489     {
490         //
491         // Unpend the PendSV interrupt.
492         //
493         SCB->ICSR |= SCB_ICSR_PENDSVCLR_Msk;
494     } else if (interruptNumber == FAULT_SYSTICK)
495     {
496         //
497         // Unpend the SysTick interrupt.
498         //
499         SCB->ICSR |= SCB_ICSR_PENDSTCLR_Msk;
500     } else if (interruptNumber >= 16)
501     {
502         //
503         // Unpend the general interrupt.
504         //
505         HWREG32 (g_pulUnpendRegs[(interruptNumber - 16) / 32]) = 1
506                 << ((interruptNumber - 16) & 31);
507     }
508 }
509
510 void Interrupt_setPriorityMask(uint8_t priorityMask)
511 {
512     CPU_basepriSet(priorityMask);
513 }
514
515 uint8_t Interrupt_getPriorityMask(void)
516 {
517     return (CPU_basepriGet());
518 }
519
520 void Interrupt_setVectorTableAddress(uint32_t addr)
521 {
522     SCB->VTOR = addr;
523 }
524
525 uint32_t Interrupt_getVectorTableAddress(void)
526 {
527     return SCB->VTOR;
528 }
529
530 void Interrupt_enableSleepOnIsrExit(void)
531 {
532     SCB->SCR |= SCB_SCR_SLEEPONEXIT_Msk;
533 }
534
535 void Interrupt_disableSleepOnIsrExit(void)
536 {
537     SCB->SCR &= ~SCB_SCR_SLEEPONEXIT_Msk;
538 }