xref: /btstack/port/msp432p401lp-cc256x/ti/devices/msp432p4xx/driverlib/interrupt.c (revision 5fd0122a3e19d95e11e1f3eb8a08a2b2acb2557e)
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     uint32_t reg_value;
232     uint32_t PriorityGroupTmp = g_pulPriority[bits];
233     reg_value  =  SCB->AIRCR;                                                   /* read old register configuration     */
234     reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change                */
235     reg_value  =  (reg_value                                   |
236                   ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
237                   (PriorityGroupTmp << 8U)                      );              /* Insert write key and priority group */
238     SCB->AIRCR =  reg_value;
239 }
240 
Interrupt_getPriorityGrouping(void)241 uint32_t Interrupt_getPriorityGrouping(void)
242 {
243     uint32_t ulLoop, ulValue;
244 
245     //
246     // Read the priority grouping.
247     //
248     ulValue = SCB->AIRCR & NVIC_APINT_PRIGROUP_M;
249 
250     //
251     // Loop through the priority grouping values.
252     //
253     for (ulLoop = 0; ulLoop < NUM_PRIORITY; ulLoop++)
254     {
255         //
256         // Stop looping if this value matches.
257         //
258         if (ulValue == g_pulPriority[ulLoop])
259         {
260             break;
261         }
262     }
263 
264     //
265     // Return the number of priority bits.
266     //
267     return (ulLoop);
268 }
269 
Interrupt_setPriority(uint32_t interruptNumber,uint8_t priority)270 void Interrupt_setPriority(uint32_t interruptNumber, uint8_t priority)
271 {
272     uint32_t ulTemp;
273 
274     //
275     // Check the arguments.
276     //
277     ASSERT((interruptNumber >= 4) && (interruptNumber < (NUM_INTERRUPTS+1)));
278 
279     //
280     // Set the interrupt priority.
281     //
282     ulTemp = HWREG32(g_pulRegs[interruptNumber >> 2]);
283     ulTemp &= ~(0xFF << (8 * (interruptNumber & 3)));
284     ulTemp |= priority << (8 * (interruptNumber & 3));
285     HWREG32 (g_pulRegs[interruptNumber >> 2]) = ulTemp;
286 }
287 
Interrupt_getPriority(uint32_t interruptNumber)288 uint8_t Interrupt_getPriority(uint32_t interruptNumber)
289 {
290     //
291     // Check the arguments.
292     //
293     ASSERT((interruptNumber >= 4) && (interruptNumber < (NUM_INTERRUPTS+1)));
294 
295     //
296     // Return the interrupt priority.
297     //
298     return ((HWREG32(g_pulRegs[interruptNumber >> 2])
299             >> (8 * (interruptNumber & 3))) & 0xFF);
300 }
301 
Interrupt_enableInterrupt(uint32_t interruptNumber)302 void Interrupt_enableInterrupt(uint32_t interruptNumber)
303 {
304     //
305     // Check the arguments.
306     //
307     ASSERT(interruptNumber < (NUM_INTERRUPTS+1));
308 
309     //
310     // Determine the interrupt to enable.
311     //
312     if (interruptNumber == FAULT_MPU)
313     {
314         //
315         // Enable the MemManage interrupt.
316         //
317         SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
318     } else if (interruptNumber == FAULT_BUS)
319     {
320         //
321         // Enable the bus fault interrupt.
322         //
323         SCB->SHCSR |= SCB_SHCSR_BUSFAULTENA_Msk;
324     } else if (interruptNumber == FAULT_USAGE)
325     {
326         //
327         // Enable the usage fault interrupt.
328         //
329         SCB->SHCSR |= SCB_SHCSR_USGFAULTENA_Msk;
330     } else if (interruptNumber == FAULT_SYSTICK)
331     {
332         //
333         // Enable the System Tick interrupt.
334         //
335         SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
336     } else if (interruptNumber >= 16)
337     {
338         //
339         // Enable the general interrupt.
340         //
341         HWREG32 (g_pulEnRegs[(interruptNumber - 16) / 32]) = 1
342                 << ((interruptNumber - 16) & 31);
343     }
344 }
345 
Interrupt_disableInterrupt(uint32_t interruptNumber)346 void Interrupt_disableInterrupt(uint32_t interruptNumber)
347 {
348     //
349     // Check the arguments.
350     //
351     ASSERT(interruptNumber < (NUM_INTERRUPTS+1));
352 
353     //
354     // Determine the interrupt to disable.
355     //
356     if (interruptNumber == FAULT_MPU)
357     {
358         //
359         // Disable the MemManage interrupt.
360         //
361         SCB->SHCSR &= ~(SCB_SHCSR_MEMFAULTENA_Msk);
362     } else if (interruptNumber == FAULT_BUS)
363     {
364         //
365         // Disable the bus fault interrupt.
366         //
367         SCB->SHCSR &= ~(SCB_SHCSR_BUSFAULTENA_Msk);
368     } else if (interruptNumber == FAULT_USAGE)
369     {
370         //
371         // Disable the usage fault interrupt.
372         //
373         SCB->SHCSR &= ~(SCB_SHCSR_USGFAULTENA_Msk);
374     } else if (interruptNumber == FAULT_SYSTICK)
375     {
376         //
377         // Disable the System Tick interrupt.
378         //
379         SysTick->CTRL &= ~(SysTick_CTRL_ENABLE_Msk);
380     } else if (interruptNumber >= 16)
381     {
382         //
383         // Disable the general interrupt.
384         //
385         HWREG32 (g_pulDisRegs[(interruptNumber - 16) / 32]) = 1
386                 << ((interruptNumber - 16) & 31);
387     }
388 }
389 
Interrupt_isEnabled(uint32_t interruptNumber)390 bool Interrupt_isEnabled(uint32_t interruptNumber)
391 {
392     uint32_t ulRet;
393 
394     //
395     // Check the arguments.
396     //
397     ASSERT(interruptNumber < (NUM_INTERRUPTS+1));
398 
399     //
400     // Initialize the return value.
401     //
402     ulRet = 0;
403 
404     //
405     // Determine the interrupt to disable.
406     //
407     if (interruptNumber == FAULT_MPU)
408     {
409         //
410         // Check the MemManage interrupt.
411         //
412         ulRet = SCB->SHCSR & SCB_SHCSR_MEMFAULTENA_Msk;
413     } else if (interruptNumber == FAULT_BUS)
414     {
415         //
416         // Check the bus fault interrupt.
417         //
418         ulRet = SCB->SHCSR & SCB_SHCSR_BUSFAULTENA_Msk;
419     } else if (interruptNumber == FAULT_USAGE)
420     {
421         //
422         // Check the usage fault interrupt.
423         //
424         ulRet = SCB->SHCSR & SCB_SHCSR_USGFAULTENA_Msk;
425     } else if (interruptNumber == FAULT_SYSTICK)
426     {
427         //
428         // Check the System Tick interrupt.
429         //
430         ulRet = SysTick->CTRL & SysTick_CTRL_ENABLE_Msk;
431     } else if (interruptNumber >= 16)
432     {
433         //
434         // Check the general interrupt.
435         //
436         ulRet = HWREG32(g_pulEnRegs[(interruptNumber - 16) / 32])
437                 & (1 << ((interruptNumber - 16) & 31));
438     }
439     return (ulRet);
440 }
441 
Interrupt_pendInterrupt(uint32_t interruptNumber)442 void Interrupt_pendInterrupt(uint32_t interruptNumber)
443 {
444     //
445     // Check the arguments.
446     //
447     ASSERT(interruptNumber < (NUM_INTERRUPTS+1));
448 
449     //
450     // Determine the interrupt to pend.
451     //
452     if (interruptNumber == FAULT_NMI)
453     {
454         //
455         // Pend the NMI interrupt.
456         //
457         SCB->ICSR |= SCB_ICSR_NMIPENDSET_Msk;
458     } else if (interruptNumber == FAULT_PENDSV)
459     {
460         //
461         // Pend the PendSV interrupt.
462         //
463         SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;
464     } else if (interruptNumber == FAULT_SYSTICK)
465     {
466         //
467         // Pend the SysTick interrupt.
468         //
469         SCB->ICSR |= SCB_ICSR_PENDSTSET_Msk;
470     } else if (interruptNumber >= 16)
471     {
472         //
473         // Pend the general interrupt.
474         //
475         HWREG32 (g_pulPendRegs[(interruptNumber - 16) / 32]) = 1
476                 << ((interruptNumber - 16) & 31);
477     }
478 }
479 
Interrupt_unpendInterrupt(uint32_t interruptNumber)480 void Interrupt_unpendInterrupt(uint32_t interruptNumber)
481 {
482     //
483     // Check the arguments.
484     //
485     ASSERT(interruptNumber < (NUM_INTERRUPTS+1));
486 
487     //
488     // Determine the interrupt to unpend.
489     //
490     if (interruptNumber == FAULT_PENDSV)
491     {
492         //
493         // Unpend the PendSV interrupt.
494         //
495         SCB->ICSR |= SCB_ICSR_PENDSVCLR_Msk;
496     } else if (interruptNumber == FAULT_SYSTICK)
497     {
498         //
499         // Unpend the SysTick interrupt.
500         //
501         SCB->ICSR |= SCB_ICSR_PENDSTCLR_Msk;
502     } else if (interruptNumber >= 16)
503     {
504         //
505         // Unpend the general interrupt.
506         //
507         HWREG32 (g_pulUnpendRegs[(interruptNumber - 16) / 32]) = 1
508                 << ((interruptNumber - 16) & 31);
509     }
510 }
511 
Interrupt_setPriorityMask(uint8_t priorityMask)512 void Interrupt_setPriorityMask(uint8_t priorityMask)
513 {
514     CPU_basepriSet(priorityMask);
515 }
516 
Interrupt_getPriorityMask(void)517 uint8_t Interrupt_getPriorityMask(void)
518 {
519     return (CPU_basepriGet());
520 }
521 
Interrupt_setVectorTableAddress(uint32_t addr)522 void Interrupt_setVectorTableAddress(uint32_t addr)
523 {
524     SCB->VTOR = addr;
525 }
526 
Interrupt_getVectorTableAddress(void)527 uint32_t Interrupt_getVectorTableAddress(void)
528 {
529     return SCB->VTOR;
530 }
531 
Interrupt_enableSleepOnIsrExit(void)532 void Interrupt_enableSleepOnIsrExit(void)
533 {
534     SCB->SCR |= SCB_SCR_SLEEPONEXIT_Msk;
535 }
536 
Interrupt_disableSleepOnIsrExit(void)537 void Interrupt_disableSleepOnIsrExit(void)
538 {
539     SCB->SCR &= ~SCB_SCR_SLEEPONEXIT_Msk;
540 }
541