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