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