]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_M4F_MSP432_LaunchPad_IAR_CCS_Keil/driverlib/interrupt.c
Final V8.2.1 release ready for tagging:
[freertos] / FreeRTOS / Demo / CORTEX_M4F_MSP432_LaunchPad_IAR_CCS_Keil / driverlib / interrupt.c
1 /*
2  * -------------------------------------------
3  *    MSP432 DriverLib - v01_04_00_18 
4  * -------------------------------------------
5  *
6  * --COPYRIGHT--,BSD,BSD
7  * Copyright (c) 2015, 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
45 //*****************************************************************************
46 //
47 // This is a mapping between priority grouping encodings and the number of
48 // preemption priority bits.
49 //
50 //*****************************************************************************
51 static const uint32_t g_pulPriority[] =
52 { NVIC_APINT_PRIGROUP_0_8, NVIC_APINT_PRIGROUP_1_7, NVIC_APINT_PRIGROUP_2_6,
53 NVIC_APINT_PRIGROUP_3_5, NVIC_APINT_PRIGROUP_4_4,
54 NVIC_APINT_PRIGROUP_5_3, NVIC_APINT_PRIGROUP_6_2,
55 NVIC_APINT_PRIGROUP_7_1 };
56
57 //*****************************************************************************
58 //
59 // This is a mapping between interrupt number and the register that contains
60 // the priority encoding for that interrupt.
61 //
62 //*****************************************************************************
63 static const uint32_t g_pulRegs[] =
64 { 0, NVIC_SYS_PRI1_R, NVIC_SYS_PRI2_R, NVIC_SYS_PRI3_R, NVIC_PRI0_R,
65 NVIC_PRI1_R, NVIC_PRI2_R, NVIC_PRI3_R, NVIC_PRI4_R, NVIC_PRI5_R,
66 NVIC_PRI6_R, NVIC_PRI7_R, NVIC_PRI8_R, NVIC_PRI9_R, NVIC_PRI10_R,
67 NVIC_PRI11_R, NVIC_PRI12_R, NVIC_PRI13_R, NVIC_PRI14_R, NVIC_PRI15_R };
68
69 //*****************************************************************************
70 //
71 // This is a mapping between interrupt number (for the peripheral interrupts
72 // only) and the register that contains the interrupt enable for that
73 // interrupt.
74 //
75 //*****************************************************************************
76 static const uint32_t g_pulEnRegs[] =
77 { NVIC_EN0_R, NVIC_EN1_R };
78
79 //*****************************************************************************
80 //
81 // This is a mapping between interrupt number (for the peripheral interrupts
82 // only) and the register that contains the interrupt disable for that
83 // interrupt.
84 //
85 //*****************************************************************************
86 static const uint32_t g_pulDisRegs[] =
87 { NVIC_DIS0_R, NVIC_DIS1_R };
88
89 //*****************************************************************************
90 //
91 // This is a mapping between interrupt number (for the peripheral interrupts
92 // only) and the register that contains the interrupt pend for that interrupt.
93 //
94 //*****************************************************************************
95 static const uint32_t g_pulPendRegs[] =
96 { NVIC_PEND0_R, NVIC_PEND1_R };
97
98 //*****************************************************************************
99 //
100 // This is a mapping between interrupt number (for the peripheral interrupts
101 // only) and the register that contains the interrupt unpend for that
102 // interrupt.
103 //
104 //*****************************************************************************
105 static const uint32_t g_pulUnpendRegs[] =
106 { NVIC_UNPEND0_R, NVIC_UNPEND1_R };
107
108 //*****************************************************************************
109 //
110 //! \internal
111 //! The default interrupt handler.
112 //!
113 //! This is the default interrupt handler for all interrupts.  It simply loops
114 //! forever so that the system state is preserved for observation by a
115 //! debugger.  Since interrupts should be disabled before unregistering the
116 //! corresponding handler, this should never be called.
117 //!
118 //! \return None.
119 //
120 //*****************************************************************************
121 static void IntDefaultHandler(void)
122 {
123     //
124     // Go into an infinite loop.
125     //
126     while (1)
127     {
128     }
129 }
130
131 //*****************************************************************************
132 //
133 // The processor vector table.
134 //
135 // This contains a list of the handlers for the various interrupt sources in
136 // the system.  The layout of this list is defined by the hardware; assertion
137 // of an interrupt causes the processor to start executing directly at the
138 // address given in the corresponding location in this list.
139 //
140 //*****************************************************************************
141 #if defined(ewarm)
142 #pragma data_alignment=1024
143 static __no_init void (*g_pfnRAMVectors[NUM_INTERRUPTS+1])(void) @ "VTABLE";
144 #elif defined(ccs)
145 #pragma DATA_ALIGN(g_pfnRAMVectors, 1024)
146 #pragma DATA_SECTION(g_pfnRAMVectors, ".vtable")
147 void (*g_pfnRAMVectors[NUM_INTERRUPTS + 1])(void);
148 #else
149 static __attribute__((section("vtable")))
150 void (*g_pfnRAMVectors[NUM_INTERRUPTS+1])(void) __attribute__((aligned(1024)));
151 #endif
152
153 bool Interrupt_enableMaster(void)
154 {
155     //
156     // Enable processor interrupts.
157     //
158     return (CPU_cpsie());
159 }
160
161 bool Interrupt_disableMaster(void)
162 {
163     //
164     // Disable processor interrupts.
165     //
166     return (CPU_cpsid());
167 }
168
169 void Interrupt_registerInterrupt(uint32_t interruptNumber,
170         void (*intHandler)(void))
171 {
172     uint32_t ulIdx, ulValue;
173
174     //
175     // Check the arguments.
176     //
177     ASSERT(interruptNumber < (NUM_INTERRUPTS+1));
178
179     //
180     // Make sure that the RAM vector table is correctly aligned.
181     //
182     ASSERT(((uint32_t) g_pfnRAMVectors & 0x000000ff) == 0);
183
184     //
185     // See if the RAM vector table has been initialized.
186     //
187     if (SCB->VTOR != (uint32_t) g_pfnRAMVectors)
188     {
189         //
190         // Copy the vector table from the beginning of FLASH to the RAM vector
191         // table.
192         //
193         ulValue = SCB->VTOR;
194         for (ulIdx = 0; ulIdx < (NUM_INTERRUPTS + 1); ulIdx++)
195         {
196             g_pfnRAMVectors[ulIdx] = (void (*)(void)) HWREG32(
197                     (ulIdx * 4) + ulValue);
198         }
199
200         //
201         // Point the NVIC at the RAM vector table.
202         //
203         SCB->VTOR = (uint32_t) g_pfnRAMVectors;
204     }
205
206     //
207     // Save the interrupt handler.
208     //
209     g_pfnRAMVectors[interruptNumber] = intHandler;
210 }
211
212 void Interrupt_unregisterInterrupt(uint32_t interruptNumber)
213 {
214     //
215     // Check the arguments.
216     //
217     ASSERT(interruptNumber < (NUM_INTERRUPTS+1));
218
219     //
220     // Reset the interrupt handler.
221     //
222     g_pfnRAMVectors[interruptNumber] = IntDefaultHandler;
223 }
224
225 void Interrupt_setPriorityGrouping(uint32_t bits)
226 {
227     //
228     // Check the arguments.
229     //
230     ASSERT(bits < NUM_PRIORITY);
231
232     //
233     // Set the priority grouping.
234     //
235     SCB->AIRCR = SCB_AIRCR_VECTKEY_M | g_pulPriority[bits];
236 }
237
238 uint32_t Interrupt_getPriorityGrouping(void)
239 {
240     uint32_t ulLoop, ulValue;
241
242     //
243     // Read the priority grouping.
244     //
245     ulValue = SCB->AIRCR & NVIC_APINT_PRIGROUP_M;
246
247     //
248     // Loop through the priority grouping values.
249     //
250     for (ulLoop = 0; ulLoop < NUM_PRIORITY; ulLoop++)
251     {
252         //
253         // Stop looping if this value matches.
254         //
255         if (ulValue == g_pulPriority[ulLoop])
256         {
257             break;
258         }
259     }
260
261     //
262     // Return the number of priority bits.
263     //
264     return (ulLoop);
265 }
266
267 void Interrupt_setPriority(uint32_t interruptNumber, uint8_t priority)
268 {
269     uint32_t ulTemp;
270
271     //
272     // Check the arguments.
273     //
274     ASSERT((interruptNumber >= 4) && (interruptNumber < (NUM_INTERRUPTS+1)));
275
276     //
277     // Set the interrupt priority.
278     //
279     ulTemp = HWREG32(g_pulRegs[interruptNumber >> 2]);
280     ulTemp &= ~(0xFF << (8 * (interruptNumber & 3)));
281     ulTemp |= priority << (8 * (interruptNumber & 3));
282     HWREG32 (g_pulRegs[interruptNumber >> 2]) = ulTemp;
283 }
284
285 uint8_t Interrupt_getPriority(uint32_t interruptNumber)
286 {
287     //
288     // Check the arguments.
289     //
290     ASSERT((interruptNumber >= 4) && (interruptNumber < (NUM_INTERRUPTS+1)));
291
292     //
293     // Return the interrupt priority.
294     //
295     return ((HWREG32(g_pulRegs[interruptNumber >> 2])
296             >> (8 * (interruptNumber & 3))) & 0xFF);
297 }
298
299 void Interrupt_enableInterrupt(uint32_t interruptNumber)
300 {
301     //
302     // Check the arguments.
303     //
304     ASSERT(interruptNumber < (NUM_INTERRUPTS+1));
305
306     //
307     // Determine the interrupt to enable.
308     //
309     if (interruptNumber == FAULT_MPU)
310     {
311         //
312         // Enable the MemManage interrupt.
313         //
314         SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA;
315     } else if (interruptNumber == FAULT_BUS)
316     {
317         //
318         // Enable the bus fault interrupt.
319         //
320         SCB->SHCSR |= SCB_SHCSR_BUSFAULTENA;
321     } else if (interruptNumber == FAULT_USAGE)
322     {
323         //
324         // Enable the usage fault interrupt.
325         //
326         SCB->SHCSR |= SCB_SHCSR_USGFAULTENA;
327     } else if (interruptNumber == FAULT_SYSTICK)
328     {
329         //
330         // Enable the System Tick interrupt.
331         //
332         SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
333     } else if (interruptNumber >= 16)
334     {
335         //
336         // Enable the general interrupt.
337         //
338         HWREG32 (g_pulEnRegs[(interruptNumber - 16) / 32]) = 1
339                 << ((interruptNumber - 16) & 31);
340     }
341 }
342
343 void Interrupt_disableInterrupt(uint32_t interruptNumber)
344 {
345     //
346     // Check the arguments.
347     //
348     ASSERT(interruptNumber < (NUM_INTERRUPTS+1));
349
350     //
351     // Determine the interrupt to disable.
352     //
353     if (interruptNumber == FAULT_MPU)
354     {
355         //
356         // Disable the MemManage interrupt.
357         //
358         SCB->SHCSR &= ~(SCB_SHCSR_MEMFAULTENA);
359     } else if (interruptNumber == FAULT_BUS)
360     {
361         //
362         // Disable the bus fault interrupt.
363         //
364         SCB->SHCSR &= ~(SCB_SHCSR_BUSFAULTENA);
365     } else if (interruptNumber == FAULT_USAGE)
366     {
367         //
368         // Disable the usage fault interrupt.
369         //
370         SCB->SHCSR &= ~(SCB_SHCSR_USGFAULTENA);
371     } else if (interruptNumber == FAULT_SYSTICK)
372     {
373         //
374         // Disable the System Tick interrupt.
375         //
376         SysTick->CTRL &= ~(SysTick_CTRL_ENABLE_Msk);
377     } else if (interruptNumber >= 16)
378     {
379         //
380         // Disable the general interrupt.
381         //
382         HWREG32 (g_pulDisRegs[(interruptNumber - 16) / 32]) = 1
383                 << ((interruptNumber - 16) & 31);
384     }
385 }
386
387 bool Interrupt_isEnabled(uint32_t interruptNumber)
388 {
389     uint32_t ulRet;
390
391     //
392     // Check the arguments.
393     //
394     ASSERT(interruptNumber < (NUM_INTERRUPTS+1));
395
396     //
397     // Initialize the return value.
398     //
399     ulRet = 0;
400
401     //
402     // Determine the interrupt to disable.
403     //
404     if (interruptNumber == FAULT_MPU)
405     {
406         //
407         // Check the MemManage interrupt.
408         //
409         ulRet = SCB->SHCSR & SCB_SHCSR_MEMFAULTENA;
410     } else if (interruptNumber == FAULT_BUS)
411     {
412         //
413         // Check the bus fault interrupt.
414         //
415         ulRet = SCB->SHCSR & SCB_SHCSR_BUSFAULTENA;
416     } else if (interruptNumber == FAULT_USAGE)
417     {
418         //
419         // Check the usage fault interrupt.
420         //
421         ulRet = SCB->SHCSR & SCB_SHCSR_USGFAULTENA;
422     } else if (interruptNumber == FAULT_SYSTICK)
423     {
424         //
425         // Check the System Tick interrupt.
426         //
427         ulRet = SysTick->CTRL & SysTick_CTRL_ENABLE_Msk;
428     } else if (interruptNumber >= 16)
429     {
430         //
431         // Check the general interrupt.
432         //
433         ulRet = HWREG32(g_pulEnRegs[(interruptNumber - 16) / 32])
434                 & (1 << ((interruptNumber - 16) & 31));
435     }
436     return (ulRet);
437 }
438
439 void Interrupt_pendInterrupt(uint32_t interruptNumber)
440 {
441     //
442     // Check the arguments.
443     //
444     ASSERT(interruptNumber < (NUM_INTERRUPTS+1));
445
446     //
447     // Determine the interrupt to pend.
448     //
449     if (interruptNumber == FAULT_NMI)
450     {
451         //
452         // Pend the NMI interrupt.
453         //
454         SCB->ICSR |= SCB_ICSR_NMIPENDSET;
455     } else if (interruptNumber == FAULT_PENDSV)
456     {
457         //
458         // Pend the PendSV interrupt.
459         //
460         SCB->ICSR |= SCB_ICSR_PENDSVSET;
461     } else if (interruptNumber == FAULT_SYSTICK)
462     {
463         //
464         // Pend the SysTick interrupt.
465         //
466         SCB->ICSR |= SCB_ICSR_PENDSTSET;
467     } else if (interruptNumber >= 16)
468     {
469         //
470         // Pend the general interrupt.
471         //
472         HWREG32 (g_pulPendRegs[(interruptNumber - 16) / 32]) = 1
473                 << ((interruptNumber - 16) & 31);
474     }
475 }
476
477 void Interrupt_unpendInterrupt(uint32_t interruptNumber)
478 {
479     //
480     // Check the arguments.
481     //
482     ASSERT(interruptNumber < (NUM_INTERRUPTS+1));
483
484     //
485     // Determine the interrupt to unpend.
486     //
487     if (interruptNumber == FAULT_PENDSV)
488     {
489         //
490         // Unpend the PendSV interrupt.
491         //
492         SCB->ICSR |= SCB_ICSR_PENDSVCLR;
493     } else if (interruptNumber == FAULT_SYSTICK)
494     {
495         //
496         // Unpend the SysTick interrupt.
497         //
498         SCB->ICSR |= SCB_ICSR_PENDSTCLR;
499     } else if (interruptNumber >= 16)
500     {
501         //
502         // Unpend the general interrupt.
503         //
504         HWREG32 (g_pulUnpendRegs[(interruptNumber - 16) / 32]) = 1
505                 << ((interruptNumber - 16) & 31);
506     }
507 }
508
509 void Interrupt_setPriorityMask(uint8_t priorityMask)
510 {
511     CPU_basepriSet(priorityMask);
512 }
513
514 uint8_t Interrupt_getPriorityMask(void)
515 {
516     return (CPU_basepriGet());
517 }
518
519 void Interrupt_setVectorTableAddress(uint32_t addr)
520 {
521     SCB->VTOR = addr;
522 }
523
524 uint32_t Interrupt_getVectorTableAddress(void)
525 {
526     return SCB->VTOR;
527 }
528
529 void Interrupt_enableSleepOnIsrExit(void)
530 {
531     SCB->SCR |= SCB_SCR_SLEEPONEXIT;
532 }
533
534 void Interrupt_disableSleepOnIsrExit(void)
535 {
536     SCB->SCR &= ~SCB_SCR_SLEEPONEXIT;
537 }