1 /******************************************************************************
2 * Filename: interrupt.c
3 * Revised: 2015-11-16 20:04:11 +0100 (Mon, 16 Nov 2015)
4 * Revision: 45095
5 *
6 * Description: Driver for the NVIC Interrupt Controller.
7 *
8 * Copyright (c) 2015, Texas Instruments Incorporated
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions are met:
13 *
14 * 1) Redistributions of source code must retain the above copyright notice,
15 * this list of conditions and the following disclaimer.
16 *
17 * 2) Redistributions in binary form must reproduce the above copyright notice,
18 * this list of conditions and the following disclaimer in the documentation
19 * and/or other materials provided with the distribution.
20 *
21 * 3) Neither the name of the ORGANIZATION nor the names of its contributors may
22 * be used to endorse or promote products derived from this software without
23 * specific prior written permission.
24 *
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, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
29 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 *
37 ******************************************************************************/
38
39 #include <driverlib/interrupt.h>
40
41 //*****************************************************************************
42 //
43 // Handle support for DriverLib in ROM:
44 // This section will undo prototype renaming made in the header file
45 //
46 //*****************************************************************************
47 #if !defined(DOXYGEN)
48 #undef IntRegister
49 #define IntRegister NOROM_IntRegister
50 #undef IntUnregister
51 #define IntUnregister NOROM_IntUnregister
52 #undef IntPriorityGroupingSet
53 #define IntPriorityGroupingSet NOROM_IntPriorityGroupingSet
54 #undef IntPriorityGroupingGet
55 #define IntPriorityGroupingGet NOROM_IntPriorityGroupingGet
56 #undef IntPrioritySet
57 #define IntPrioritySet NOROM_IntPrioritySet
58 #undef IntPriorityGet
59 #define IntPriorityGet NOROM_IntPriorityGet
60 #undef IntEnable
61 #define IntEnable NOROM_IntEnable
62 #undef IntDisable
63 #define IntDisable NOROM_IntDisable
64 #undef IntPendSet
65 #define IntPendSet NOROM_IntPendSet
66 #undef IntPendGet
67 #define IntPendGet NOROM_IntPendGet
68 #undef IntPendClear
69 #define IntPendClear NOROM_IntPendClear
70 #endif
71
72 //*****************************************************************************
73 //
74 //! This is a mapping between priority grouping encodings and the number of
75 //! preemption priority bits.
76 //
77 //*****************************************************************************
78 static const uint32_t g_pui32Priority[] =
79 {
80 NVIC_APINT_PRIGROUP_0_8, NVIC_APINT_PRIGROUP_1_7, NVIC_APINT_PRIGROUP_2_6,
81 NVIC_APINT_PRIGROUP_3_5, NVIC_APINT_PRIGROUP_4_4, NVIC_APINT_PRIGROUP_5_3,
82 NVIC_APINT_PRIGROUP_6_2, NVIC_APINT_PRIGROUP_7_1
83 };
84
85 //*****************************************************************************
86 //
87 //! This is a mapping between interrupt number and the register that contains
88 //! the priority encoding for that interrupt.
89 //
90 //*****************************************************************************
91 static const uint32_t g_pui32Regs[] =
92 {
93 0, NVIC_SYS_PRI1, NVIC_SYS_PRI2, NVIC_SYS_PRI3, NVIC_PRI0, NVIC_PRI1,
94 NVIC_PRI2, NVIC_PRI3, NVIC_PRI4, NVIC_PRI5, NVIC_PRI6, NVIC_PRI7,
95 NVIC_PRI8, NVIC_PRI9, NVIC_PRI10, NVIC_PRI11, NVIC_PRI12, NVIC_PRI13
96 };
97
98 //*****************************************************************************
99 //
100 //! \brief The default interrupt handler.
101 //!
102 //! This is the default interrupt handler for all interrupts. It simply loops
103 //! forever so that the system state is preserved for observation by a
104 //! debugger. Since interrupts should be disabled before unregistering the
105 //! corresponding handler, this should never be called.
106 //!
107 //! \return None
108 //
109 //*****************************************************************************
110 static void
IntDefaultHandler(void)111 IntDefaultHandler(void)
112 {
113 //
114 // Go into an infinite loop.
115 //
116 while(1)
117 {
118 }
119 }
120
121 //*****************************************************************************
122 //
123 // The processor vector table.
124 //
125 // This contains a list of the handlers for the various interrupt sources in
126 // the system. The layout of this list is defined by the hardware; assertion
127 // of an interrupt causes the processor to start executing directly at the
128 // address given in the corresponding location in this list.
129 //
130 //*****************************************************************************
131 #if defined(__IAR_SYSTEMS_ICC__)
132 #pragma data_alignment=256
133 static __no_init void (*g_pfnRAMVectors[NUM_INTERRUPTS])(void) @ ".vtable_ram";
134 #elif defined(__TI_COMPILER_VERSION__) || defined(DOXYGEN)
135 #pragma DATA_ALIGN(g_pfnRAMVectors, 256)
136 #pragma DATA_SECTION(g_pfnRAMVectors, ".vtable_ram")
137 void (*g_pfnRAMVectors[NUM_INTERRUPTS])(void);
138 #elif defined (__CC_ARM)
139 static __attribute__((section("vtable_ram")))
140 void (*g_pfnRAMVectors[NUM_INTERRUPTS])(void) __attribute__((aligned(256)));
141 #else
142 static __attribute__((section("vtable_ram")))
143 void (*g_pfnRAMVectors[NUM_INTERRUPTS])(void) __attribute__((aligned(256)));
144 #endif
145
146 //*****************************************************************************
147 //
148 //! Registers a function to be called when an interrupt occurs.
149 //
150 //*****************************************************************************
151 void
IntRegister(uint32_t ui32Interrupt,void (* pfnHandler)(void))152 IntRegister(uint32_t ui32Interrupt, void (*pfnHandler)(void))
153 {
154 uint32_t ui32Idx, ui32Value;
155
156 //
157 // Check the arguments.
158 //
159 ASSERT(ui32Interrupt < NUM_INTERRUPTS);
160
161 //
162 // Make sure that the RAM vector table is correctly aligned.
163 //
164 ASSERT(((uint32_t)g_pfnRAMVectors & 0x000000ff) == 0);
165
166 //
167 // See if the RAM vector table has been initialized.
168 //
169 if(HWREG(NVIC_VTABLE) != (uint32_t)g_pfnRAMVectors)
170 {
171 //
172 // Copy the vector table from the beginning of FLASH to the RAM vector
173 // table.
174 //
175 ui32Value = HWREG(NVIC_VTABLE);
176 for(ui32Idx = 0; ui32Idx < NUM_INTERRUPTS; ui32Idx++)
177 {
178 g_pfnRAMVectors[ui32Idx] = (void (*)(void))HWREG((ui32Idx * 4) +
179 ui32Value);
180 }
181
182 //
183 // Point NVIC at the RAM vector table.
184 //
185 HWREG(NVIC_VTABLE) = (uint32_t)g_pfnRAMVectors;
186 }
187
188 //
189 // Save the interrupt handler.
190 //
191 g_pfnRAMVectors[ui32Interrupt] = pfnHandler;
192 }
193
194 //*****************************************************************************
195 //
196 //! Unregisters the function to be called when an interrupt occurs.
197 //
198 //*****************************************************************************
199 void
IntUnregister(uint32_t ui32Interrupt)200 IntUnregister(uint32_t ui32Interrupt)
201 {
202 //
203 // Check the arguments.
204 //
205 ASSERT(ui32Interrupt < NUM_INTERRUPTS);
206
207 //
208 // Reset the interrupt handler.
209 //
210 g_pfnRAMVectors[ui32Interrupt] = IntDefaultHandler;
211 }
212
213 //*****************************************************************************
214 //
215 //! Sets the priority grouping of the interrupt controller.
216 //
217 //*****************************************************************************
218 void
IntPriorityGroupingSet(uint32_t ui32Bits)219 IntPriorityGroupingSet(uint32_t ui32Bits)
220 {
221 //
222 // Check the arguments.
223 //
224 ASSERT(ui32Bits < NUM_PRIORITY);
225
226 //
227 // Set the priority grouping.
228 //
229 HWREG(NVIC_APINT) = NVIC_APINT_VECTKEY | g_pui32Priority[ui32Bits];
230 }
231
232 //*****************************************************************************
233 //
234 //! Gets the priority grouping of the interrupt controller
235 //
236 //*****************************************************************************
237 uint32_t
IntPriorityGroupingGet(void)238 IntPriorityGroupingGet(void)
239 {
240 uint32_t ui32Loop, ui32Value;
241
242 //
243 // Read the priority grouping.
244 //
245 ui32Value = HWREG(NVIC_APINT) & NVIC_APINT_PRIGROUP_M;
246
247 //
248 // Loop through the priority grouping values.
249 //
250 for(ui32Loop = 0; ui32Loop < NUM_PRIORITY; ui32Loop++)
251 {
252 //
253 // Stop looping if this value matches.
254 //
255 if(ui32Value == g_pui32Priority[ui32Loop])
256 {
257 break;
258 }
259 }
260
261 //
262 // Return the number of priority bits.
263 //
264 return(ui32Loop);
265 }
266
267 //*****************************************************************************
268 //
269 //! Sets the priority of an interrupt
270 //
271 //*****************************************************************************
272 void
IntPrioritySet(uint32_t ui32Interrupt,uint8_t ui8Priority)273 IntPrioritySet(uint32_t ui32Interrupt, uint8_t ui8Priority)
274 {
275 uint32_t ui32Temp;
276
277 //
278 // Check the arguments.
279 //
280 ASSERT((ui32Interrupt >= 4) && (ui32Interrupt < NUM_INTERRUPTS));
281 ASSERT(ui8Priority <= INT_PRI_LEVEL7);
282
283 //
284 // Set the interrupt priority.
285 //
286 ui32Temp = HWREG(g_pui32Regs[ui32Interrupt >> 2]);
287 ui32Temp &= ~(0xFF << (8 * (ui32Interrupt & 3)));
288 ui32Temp |= ui8Priority << (8 * (ui32Interrupt & 3));
289 HWREG(g_pui32Regs[ui32Interrupt >> 2]) = ui32Temp;
290 }
291
292 //*****************************************************************************
293 //
294 //! Gets the priority of an interrupt
295 //
296 //*****************************************************************************
297 int32_t
IntPriorityGet(uint32_t ui32Interrupt)298 IntPriorityGet(uint32_t ui32Interrupt)
299 {
300 //
301 // Check the arguments.
302 //
303 ASSERT((ui32Interrupt >= 4) && (ui32Interrupt < NUM_INTERRUPTS));
304
305 //
306 // Return the interrupt priority.
307 //
308 return((HWREG(g_pui32Regs[ui32Interrupt >> 2]) >> (8 * (ui32Interrupt & 3))) &
309 0xFF);
310 }
311
312 //*****************************************************************************
313 //
314 //! Enables an interrupt
315 //
316 //*****************************************************************************
317 void
IntEnable(uint32_t ui32Interrupt)318 IntEnable(uint32_t ui32Interrupt)
319 {
320 //
321 // Check the arguments.
322 //
323 ASSERT(ui32Interrupt < NUM_INTERRUPTS);
324
325 //
326 // Determine the interrupt to enable.
327 //
328 if(ui32Interrupt == INT_MEMMANAGE_FAULT)
329 {
330 //
331 // Enable the MemManage interrupt.
332 //
333 HWREG(NVIC_SYS_HND_CTRL) |= NVIC_SYS_HND_CTRL_MEM;
334 }
335 else if(ui32Interrupt == INT_BUS_FAULT)
336 {
337 //
338 // Enable the bus fault interrupt.
339 //
340 HWREG(NVIC_SYS_HND_CTRL) |= NVIC_SYS_HND_CTRL_BUS;
341 }
342 else if(ui32Interrupt == INT_USAGE_FAULT)
343 {
344 //
345 // Enable the usage fault interrupt.
346 //
347 HWREG(NVIC_SYS_HND_CTRL) |= NVIC_SYS_HND_CTRL_USAGE;
348 }
349 else if(ui32Interrupt == INT_SYSTICK)
350 {
351 //
352 // Enable the System Tick interrupt.
353 //
354 HWREG(NVIC_ST_CTRL) |= NVIC_ST_CTRL_INTEN;
355 }
356 else if((ui32Interrupt >= 16) && (ui32Interrupt <= 47))
357 {
358 //
359 // Enable the general interrupt.
360 //
361 HWREG(NVIC_EN0) = 1 << (ui32Interrupt - 16);
362 }
363 else if(ui32Interrupt >= 48)
364 {
365 //
366 // Enable the general interrupt.
367 //
368 HWREG(NVIC_EN1) = 1 << (ui32Interrupt - 48);
369 }
370 }
371
372 //*****************************************************************************
373 //
374 //! Disables an interrupt
375 //
376 //*****************************************************************************
377 void
IntDisable(uint32_t ui32Interrupt)378 IntDisable(uint32_t ui32Interrupt)
379 {
380 //
381 // Check the arguments.
382 //
383 ASSERT(ui32Interrupt < NUM_INTERRUPTS);
384
385 //
386 // Determine the interrupt to disable.
387 //
388 if(ui32Interrupt == INT_MEMMANAGE_FAULT)
389 {
390 //
391 // Disable the MemManage interrupt.
392 //
393 HWREG(NVIC_SYS_HND_CTRL) &= ~(NVIC_SYS_HND_CTRL_MEM);
394 }
395 else if(ui32Interrupt == INT_BUS_FAULT)
396 {
397 //
398 // Disable the bus fault interrupt.
399 //
400 HWREG(NVIC_SYS_HND_CTRL) &= ~(NVIC_SYS_HND_CTRL_BUS);
401 }
402 else if(ui32Interrupt == INT_USAGE_FAULT)
403 {
404 //
405 // Disable the usage fault interrupt.
406 //
407 HWREG(NVIC_SYS_HND_CTRL) &= ~(NVIC_SYS_HND_CTRL_USAGE);
408 }
409 else if(ui32Interrupt == INT_SYSTICK)
410 {
411 //
412 // Disable the System Tick interrupt.
413 //
414 HWREG(NVIC_ST_CTRL) &= ~(NVIC_ST_CTRL_INTEN);
415 }
416 else if((ui32Interrupt >= 16) && (ui32Interrupt <= 47))
417 {
418 //
419 // Disable the general interrupt.
420 //
421 HWREG(NVIC_DIS0) = 1 << (ui32Interrupt - 16);
422 }
423 else if(ui32Interrupt >= 48)
424 {
425 //
426 // Disable the general interrupt.
427 //
428 HWREG(NVIC_DIS1) = 1 << (ui32Interrupt - 48);
429 }
430 }
431
432 //*****************************************************************************
433 //
434 //! Pends an interrupt
435 //
436 //*****************************************************************************
437 void
IntPendSet(uint32_t ui32Interrupt)438 IntPendSet(uint32_t ui32Interrupt)
439 {
440 //
441 // Check the arguments.
442 //
443 ASSERT(ui32Interrupt < NUM_INTERRUPTS);
444
445 //
446 // Determine the interrupt to pend.
447 //
448 if(ui32Interrupt == INT_NMI_FAULT)
449 {
450 //
451 // Pend the NMI interrupt.
452 //
453 HWREG(NVIC_INT_CTRL) |= NVIC_INT_CTRL_NMI_SET;
454 }
455 else if(ui32Interrupt == INT_PENDSV)
456 {
457 //
458 // Pend the PendSV interrupt.
459 //
460 HWREG(NVIC_INT_CTRL) |= NVIC_INT_CTRL_PEND_SV;
461 }
462 else if(ui32Interrupt == INT_SYSTICK)
463 {
464 //
465 // Pend the SysTick interrupt.
466 //
467 HWREG(NVIC_INT_CTRL) |= NVIC_INT_CTRL_PENDSTSET;
468 }
469 else if((ui32Interrupt >= 16) && (ui32Interrupt <= 47))
470 {
471 //
472 // Pend the general interrupt.
473 //
474 HWREG(NVIC_PEND0) = 1 << (ui32Interrupt - 16);
475 }
476 else if(ui32Interrupt >= 48)
477 {
478 //
479 // Pend the general interrupt.
480 //
481 HWREG(NVIC_PEND1) = 1 << (ui32Interrupt - 48);
482 }
483 }
484
485 //*****************************************************************************
486 //
487 //! Query whether an interrupt is pending
488 //
489 //*****************************************************************************
490 bool
IntPendGet(uint32_t ui32Interrupt)491 IntPendGet(uint32_t ui32Interrupt)
492 {
493 uint32_t ui32IntPending;
494
495 //
496 // Check the arguments.
497 //
498 ASSERT(ui32Interrupt < NUM_INTERRUPTS);
499
500 //
501 // Assume no interrupts are pending.
502 //
503 ui32IntPending = 0;
504
505 //
506 // The lower 16 IRQ vectors are unsupported by this function
507 //
508 if (ui32Interrupt < 16)
509 {
510
511 return 0;
512 }
513
514 //
515 // Subtract lower 16 irq vectors
516 //
517 ui32Interrupt -= 16;
518
519 //
520 // Check if the interrupt is pending
521 //
522 ui32IntPending = HWREG(NVIC_PEND0 + (ui32Interrupt / 32));
523 ui32IntPending &= (1 << (ui32Interrupt & 31));
524
525 return ui32IntPending ? true : false;
526 }
527
528 //*****************************************************************************
529 //
530 //! Unpends an interrupt
531 //
532 //*****************************************************************************
533 void
IntPendClear(uint32_t ui32Interrupt)534 IntPendClear(uint32_t ui32Interrupt)
535 {
536 //
537 // Check the arguments.
538 //
539 ASSERT(ui32Interrupt < NUM_INTERRUPTS);
540
541 //
542 // Determine the interrupt to unpend.
543 //
544 if(ui32Interrupt == INT_PENDSV)
545 {
546 //
547 // Unpend the PendSV interrupt.
548 //
549 HWREG(NVIC_INT_CTRL) |= NVIC_INT_CTRL_UNPEND_SV;
550 }
551 else if(ui32Interrupt == INT_SYSTICK)
552 {
553 //
554 // Unpend the SysTick interrupt.
555 //
556 HWREG(NVIC_INT_CTRL) |= NVIC_INT_CTRL_PENDSTCLR;
557 }
558 else if((ui32Interrupt >= 16) && (ui32Interrupt <= 47))
559 {
560 //
561 // Unpend the general interrupt.
562 //
563 HWREG(NVIC_UNPEND0) = 1 << (ui32Interrupt - 16);
564 }
565 else if(ui32Interrupt >= 48)
566 {
567 //
568 // Unpend the general interrupt.
569 //
570 HWREG(NVIC_UNPEND1) = 1 << (ui32Interrupt - 48);
571 }
572 }
573