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