2 * -------------------------------------------
3 * MSP432 DriverLib - v01_04_00_18
4 * -------------------------------------------
6 * --COPYRIGHT--,BSD,BSD
7 * Copyright (c) 2015, Texas Instruments Incorporated
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
14 * * Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
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.
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.
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.
37 /* Standard Includes */
40 /* DriverLib Includes */
43 #include <interrupt.h>
45 //*****************************************************************************
47 // This is a mapping between priority grouping encodings and the number of
48 // preemption priority bits.
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 };
57 //*****************************************************************************
59 // This is a mapping between interrupt number and the register that contains
60 // the priority encoding for that interrupt.
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 };
69 //*****************************************************************************
71 // This is a mapping between interrupt number (for the peripheral interrupts
72 // only) and the register that contains the interrupt enable for that
75 //*****************************************************************************
76 static const uint32_t g_pulEnRegs[] =
77 { NVIC_EN0_R, NVIC_EN1_R };
79 //*****************************************************************************
81 // This is a mapping between interrupt number (for the peripheral interrupts
82 // only) and the register that contains the interrupt disable for that
85 //*****************************************************************************
86 static const uint32_t g_pulDisRegs[] =
87 { NVIC_DIS0_R, NVIC_DIS1_R };
89 //*****************************************************************************
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.
94 //*****************************************************************************
95 static const uint32_t g_pulPendRegs[] =
96 { NVIC_PEND0_R, NVIC_PEND1_R };
98 //*****************************************************************************
100 // This is a mapping between interrupt number (for the peripheral interrupts
101 // only) and the register that contains the interrupt unpend for that
104 //*****************************************************************************
105 static const uint32_t g_pulUnpendRegs[] =
106 { NVIC_UNPEND0_R, NVIC_UNPEND1_R };
108 //*****************************************************************************
111 //! The default interrupt handler.
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.
120 //*****************************************************************************
121 static void IntDefaultHandler(void)
124 // Go into an infinite loop.
131 //*****************************************************************************
133 // The processor vector table.
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.
140 //*****************************************************************************
142 #pragma data_alignment=1024
143 static __no_init void (*g_pfnRAMVectors[NUM_INTERRUPTS+1])(void) @ "VTABLE";
145 #pragma DATA_ALIGN(g_pfnRAMVectors, 1024)
146 #pragma DATA_SECTION(g_pfnRAMVectors, ".vtable")
147 void (*g_pfnRAMVectors[NUM_INTERRUPTS + 1])(void);
149 static __attribute__((section("vtable")))
150 void (*g_pfnRAMVectors[NUM_INTERRUPTS+1])(void) __attribute__((aligned(1024)));
153 bool Interrupt_enableMaster(void)
156 // Enable processor interrupts.
158 return (CPU_cpsie());
161 bool Interrupt_disableMaster(void)
164 // Disable processor interrupts.
166 return (CPU_cpsid());
169 void Interrupt_registerInterrupt(uint32_t interruptNumber,
170 void (*intHandler)(void))
172 uint32_t ulIdx, ulValue;
175 // Check the arguments.
177 ASSERT(interruptNumber < (NUM_INTERRUPTS+1));
180 // Make sure that the RAM vector table is correctly aligned.
182 ASSERT(((uint32_t) g_pfnRAMVectors & 0x000000ff) == 0);
185 // See if the RAM vector table has been initialized.
187 if (SCB->VTOR != (uint32_t) g_pfnRAMVectors)
190 // Copy the vector table from the beginning of FLASH to the RAM vector
194 for (ulIdx = 0; ulIdx < (NUM_INTERRUPTS + 1); ulIdx++)
196 g_pfnRAMVectors[ulIdx] = (void (*)(void)) HWREG32(
197 (ulIdx * 4) + ulValue);
201 // Point the NVIC at the RAM vector table.
203 SCB->VTOR = (uint32_t) g_pfnRAMVectors;
207 // Save the interrupt handler.
209 g_pfnRAMVectors[interruptNumber] = intHandler;
212 void Interrupt_unregisterInterrupt(uint32_t interruptNumber)
215 // Check the arguments.
217 ASSERT(interruptNumber < (NUM_INTERRUPTS+1));
220 // Reset the interrupt handler.
222 g_pfnRAMVectors[interruptNumber] = IntDefaultHandler;
225 void Interrupt_setPriorityGrouping(uint32_t bits)
228 // Check the arguments.
230 ASSERT(bits < NUM_PRIORITY);
233 // Set the priority grouping.
235 SCB->AIRCR = SCB_AIRCR_VECTKEY_M | g_pulPriority[bits];
238 uint32_t Interrupt_getPriorityGrouping(void)
240 uint32_t ulLoop, ulValue;
243 // Read the priority grouping.
245 ulValue = SCB->AIRCR & NVIC_APINT_PRIGROUP_M;
248 // Loop through the priority grouping values.
250 for (ulLoop = 0; ulLoop < NUM_PRIORITY; ulLoop++)
253 // Stop looping if this value matches.
255 if (ulValue == g_pulPriority[ulLoop])
262 // Return the number of priority bits.
267 void Interrupt_setPriority(uint32_t interruptNumber, uint8_t priority)
272 // Check the arguments.
274 ASSERT((interruptNumber >= 4) && (interruptNumber < (NUM_INTERRUPTS+1)));
277 // Set the interrupt priority.
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;
285 uint8_t Interrupt_getPriority(uint32_t interruptNumber)
288 // Check the arguments.
290 ASSERT((interruptNumber >= 4) && (interruptNumber < (NUM_INTERRUPTS+1)));
293 // Return the interrupt priority.
295 return ((HWREG32(g_pulRegs[interruptNumber >> 2])
296 >> (8 * (interruptNumber & 3))) & 0xFF);
299 void Interrupt_enableInterrupt(uint32_t interruptNumber)
302 // Check the arguments.
304 ASSERT(interruptNumber < (NUM_INTERRUPTS+1));
307 // Determine the interrupt to enable.
309 if (interruptNumber == FAULT_MPU)
312 // Enable the MemManage interrupt.
314 SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA;
315 } else if (interruptNumber == FAULT_BUS)
318 // Enable the bus fault interrupt.
320 SCB->SHCSR |= SCB_SHCSR_BUSFAULTENA;
321 } else if (interruptNumber == FAULT_USAGE)
324 // Enable the usage fault interrupt.
326 SCB->SHCSR |= SCB_SHCSR_USGFAULTENA;
327 } else if (interruptNumber == FAULT_SYSTICK)
330 // Enable the System Tick interrupt.
332 SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
333 } else if (interruptNumber >= 16)
336 // Enable the general interrupt.
338 HWREG32 (g_pulEnRegs[(interruptNumber - 16) / 32]) = 1
339 << ((interruptNumber - 16) & 31);
343 void Interrupt_disableInterrupt(uint32_t interruptNumber)
346 // Check the arguments.
348 ASSERT(interruptNumber < (NUM_INTERRUPTS+1));
351 // Determine the interrupt to disable.
353 if (interruptNumber == FAULT_MPU)
356 // Disable the MemManage interrupt.
358 SCB->SHCSR &= ~(SCB_SHCSR_MEMFAULTENA);
359 } else if (interruptNumber == FAULT_BUS)
362 // Disable the bus fault interrupt.
364 SCB->SHCSR &= ~(SCB_SHCSR_BUSFAULTENA);
365 } else if (interruptNumber == FAULT_USAGE)
368 // Disable the usage fault interrupt.
370 SCB->SHCSR &= ~(SCB_SHCSR_USGFAULTENA);
371 } else if (interruptNumber == FAULT_SYSTICK)
374 // Disable the System Tick interrupt.
376 SysTick->CTRL &= ~(SysTick_CTRL_ENABLE_Msk);
377 } else if (interruptNumber >= 16)
380 // Disable the general interrupt.
382 HWREG32 (g_pulDisRegs[(interruptNumber - 16) / 32]) = 1
383 << ((interruptNumber - 16) & 31);
387 bool Interrupt_isEnabled(uint32_t interruptNumber)
392 // Check the arguments.
394 ASSERT(interruptNumber < (NUM_INTERRUPTS+1));
397 // Initialize the return value.
402 // Determine the interrupt to disable.
404 if (interruptNumber == FAULT_MPU)
407 // Check the MemManage interrupt.
409 ulRet = SCB->SHCSR & SCB_SHCSR_MEMFAULTENA;
410 } else if (interruptNumber == FAULT_BUS)
413 // Check the bus fault interrupt.
415 ulRet = SCB->SHCSR & SCB_SHCSR_BUSFAULTENA;
416 } else if (interruptNumber == FAULT_USAGE)
419 // Check the usage fault interrupt.
421 ulRet = SCB->SHCSR & SCB_SHCSR_USGFAULTENA;
422 } else if (interruptNumber == FAULT_SYSTICK)
425 // Check the System Tick interrupt.
427 ulRet = SysTick->CTRL & SysTick_CTRL_ENABLE_Msk;
428 } else if (interruptNumber >= 16)
431 // Check the general interrupt.
433 ulRet = HWREG32(g_pulEnRegs[(interruptNumber - 16) / 32])
434 & (1 << ((interruptNumber - 16) & 31));
439 void Interrupt_pendInterrupt(uint32_t interruptNumber)
442 // Check the arguments.
444 ASSERT(interruptNumber < (NUM_INTERRUPTS+1));
447 // Determine the interrupt to pend.
449 if (interruptNumber == FAULT_NMI)
452 // Pend the NMI interrupt.
454 SCB->ICSR |= SCB_ICSR_NMIPENDSET;
455 } else if (interruptNumber == FAULT_PENDSV)
458 // Pend the PendSV interrupt.
460 SCB->ICSR |= SCB_ICSR_PENDSVSET;
461 } else if (interruptNumber == FAULT_SYSTICK)
464 // Pend the SysTick interrupt.
466 SCB->ICSR |= SCB_ICSR_PENDSTSET;
467 } else if (interruptNumber >= 16)
470 // Pend the general interrupt.
472 HWREG32 (g_pulPendRegs[(interruptNumber - 16) / 32]) = 1
473 << ((interruptNumber - 16) & 31);
477 void Interrupt_unpendInterrupt(uint32_t interruptNumber)
480 // Check the arguments.
482 ASSERT(interruptNumber < (NUM_INTERRUPTS+1));
485 // Determine the interrupt to unpend.
487 if (interruptNumber == FAULT_PENDSV)
490 // Unpend the PendSV interrupt.
492 SCB->ICSR |= SCB_ICSR_PENDSVCLR;
493 } else if (interruptNumber == FAULT_SYSTICK)
496 // Unpend the SysTick interrupt.
498 SCB->ICSR |= SCB_ICSR_PENDSTCLR;
499 } else if (interruptNumber >= 16)
502 // Unpend the general interrupt.
504 HWREG32 (g_pulUnpendRegs[(interruptNumber - 16) / 32]) = 1
505 << ((interruptNumber - 16) & 31);
509 void Interrupt_setPriorityMask(uint8_t priorityMask)
511 CPU_basepriSet(priorityMask);
514 uint8_t Interrupt_getPriorityMask(void)
516 return (CPU_basepriGet());
519 void Interrupt_setVectorTableAddress(uint32_t addr)
524 uint32_t Interrupt_getVectorTableAddress(void)
529 void Interrupt_enableSleepOnIsrExit(void)
531 SCB->SCR |= SCB_SCR_SLEEPONEXIT;
534 void Interrupt_disableSleepOnIsrExit(void)
536 SCB->SCR &= ~SCB_SCR_SLEEPONEXIT;