CC26xx Driver Library
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
interrupt.c
Go to the documentation of this file.
1 /******************************************************************************
2 * Filename: interrupt.c
3 * Revised: 2015-01-13 16:59:55 +0100 (ti, 13 jan 2015)
4 * Revision: 42365
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 #ifndef DRIVERLIB_GENERATE_ROM
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 //
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 //
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 //
109 //
110 //*****************************************************************************
111 static void
112 IntDefaultHandler(void)
113 {
114  //
115  // Go into an infinite loop.
116  //
117  while(1)
118  {
119  }
120 }
121 
122 //*****************************************************************************
123 //
124 // The processor vector table.
125 //
126 // This contains a list of the handlers for the various interrupt sources in
127 // the system. The layout of this list is defined by the hardware; assertion
128 // of an interrupt causes the processor to start executing directly at the
129 // address given in the corresponding location in this list.
130 //
131 // TBD : FIX Remember to remove "zero_init" from interrupt vector declaration
132 // TBD : How big must the interrupt table be?
133 //
134 //*****************************************************************************
135 #if defined(__IAR_SYSTEMS_ICC__)
136 #pragma data_alignment=256
137 static __no_init void (*g_pfnRAMVectors[NUM_INTERRUPTS])(void) @ ".vtable_ram";
138 #elif defined(__TI_COMPILER_VERSION__) || defined(DOXYGEN)
139 #pragma DATA_ALIGN(g_pfnRAMVectors, 256)
140 #pragma DATA_SECTION(g_pfnRAMVectors, ".vtable_ram")
141 void (*g_pfnRAMVectors[NUM_INTERRUPTS])(void);
142 #elif defined (rvmdk)
143 static __attribute__((section("vtable_ram")))
144 void (*g_pfnRAMVectors[NUM_INTERRUPTS])(void) __attribute__((aligned(256),
145  zero_init));
146 #else
147 static __attribute__((section("vtable_ram")))
148 void (*g_pfnRAMVectors[NUM_INTERRUPTS])(void) __attribute__((aligned(256)));
149 #endif
150 
151 //*****************************************************************************
152 //
154 //
155 //*****************************************************************************
156 void
157 IntRegister(uint32_t ui32Interrupt, void (*pfnHandler)(void))
158 {
159  uint32_t ui32Idx, ui32Value;
160 
161  //
162  // Check the arguments.
163  //
164  ASSERT(ui32Interrupt < NUM_INTERRUPTS);
165 
166  //
167  // Make sure that the RAM vector table is correctly aligned.
168  //
169  ASSERT(((uint32_t)g_pfnRAMVectors & 0x000000ff) == 0);
170 
171  //
172  // See if the RAM vector table has been initialized.
173  //
174  if(HWREG(NVIC_VTABLE) != (uint32_t)g_pfnRAMVectors)
175  {
176  //
177  // Copy the vector table from the beginning of FLASH to the RAM vector
178  // table.
179  //
180  ui32Value = HWREG(NVIC_VTABLE);
181  for(ui32Idx = 0; ui32Idx < NUM_INTERRUPTS; ui32Idx++)
182  {
183  g_pfnRAMVectors[ui32Idx] = (void (*)(void))HWREG((ui32Idx * 4) +
184  ui32Value);
185  }
186 
187  //
188  // Point NVIC at the RAM vector table.
189  //
190  HWREG(NVIC_VTABLE) = (uint32_t)g_pfnRAMVectors;
191  }
192 
193  //
194  // Save the interrupt handler.
195  //
196  g_pfnRAMVectors[ui32Interrupt] = pfnHandler;
197 }
198 
199 //*****************************************************************************
200 //
202 //
203 //*****************************************************************************
204 void
205 IntUnregister(uint32_t ui32Interrupt)
206 {
207  //
208  // Check the arguments.
209  //
210  ASSERT(ui32Interrupt < NUM_INTERRUPTS);
211 
212  //
213  // Reset the interrupt handler.
214  //
215  g_pfnRAMVectors[ui32Interrupt] = IntDefaultHandler;
216 }
217 
218 //*****************************************************************************
219 //
221 //
222 //*****************************************************************************
223 void
224 IntPriorityGroupingSet(uint32_t ui32Bits)
225 {
226  //
227  // Check the arguments.
228  //
229  ASSERT(ui32Bits < NUM_PRIORITY);
230 
231  //
232  // Set the priority grouping.
233  //
234  HWREG(NVIC_APINT) = NVIC_APINT_VECTKEY | g_pui32Priority[ui32Bits];
235 }
236 
237 //*****************************************************************************
238 //
240 //
241 //*****************************************************************************
242 uint32_t
244 {
245  uint32_t ui32Loop, ui32Value;
246 
247  //
248  // Read the priority grouping.
249  //
250  ui32Value = HWREG(NVIC_APINT) & NVIC_APINT_PRIGROUP_M;
251 
252  //
253  // Loop through the priority grouping values.
254  //
255  for(ui32Loop = 0; ui32Loop < NUM_PRIORITY; ui32Loop++)
256  {
257  //
258  // Stop looping if this value matches.
259  //
260  if(ui32Value == g_pui32Priority[ui32Loop])
261  {
262  break;
263  }
264  }
265 
266  //
267  // Return the number of priority bits.
268  //
269  return(ui32Loop);
270 }
271 
272 //*****************************************************************************
273 //
275 //
276 //*****************************************************************************
277 void
278 IntPrioritySet(uint32_t ui32Interrupt, uint8_t ui8Priority)
279 {
280  uint32_t ui32Temp;
281 
282  //
283  // Check the arguments.
284  //
285  ASSERT((ui32Interrupt >= 4) && (ui32Interrupt < NUM_INTERRUPTS));
286  ASSERT(ui8Priority <= INT_PRI_LEVEL7);
287 
288  //
289  // Set the interrupt priority.
290  //
291  ui32Temp = HWREG(g_pui32Regs[ui32Interrupt >> 2]);
292  ui32Temp &= ~(0xFF << (8 * (ui32Interrupt & 3)));
293  ui32Temp |= ui8Priority << (8 * (ui32Interrupt & 3));
294  HWREG(g_pui32Regs[ui32Interrupt >> 2]) = ui32Temp;
295 }
296 
297 //*****************************************************************************
298 //
300 //
301 //*****************************************************************************
302 int32_t
303 IntPriorityGet(uint32_t ui32Interrupt)
304 {
305  //
306  // Check the arguments.
307  //
308  ASSERT((ui32Interrupt >= 4) && (ui32Interrupt < NUM_INTERRUPTS));
309 
310  //
311  // Return the interrupt priority.
312  //
313  return((HWREG(g_pui32Regs[ui32Interrupt >> 2]) >> (8 * (ui32Interrupt & 3))) &
314  0xFF);
315 }
316 
317 //*****************************************************************************
318 //
320 //
321 //*****************************************************************************
322 void
323 IntEnable(uint32_t ui32Interrupt)
324 {
325  //
326  // Check the arguments.
327  //
328  ASSERT(ui32Interrupt < NUM_INTERRUPTS);
329 
330  //
331  // Determine the interrupt to enable.
332  //
333  if(ui32Interrupt == FAULT_MPU)
334  {
335  //
336  // Enable the MemManage interrupt.
337  //
338  HWREG(NVIC_SYS_HND_CTRL) |= NVIC_SYS_HND_CTRL_MEM;
339  }
340  else if(ui32Interrupt == FAULT_BUS)
341  {
342  //
343  // Enable the bus fault interrupt.
344  //
345  HWREG(NVIC_SYS_HND_CTRL) |= NVIC_SYS_HND_CTRL_BUS;
346  }
347  else if(ui32Interrupt == FAULT_USAGE)
348  {
349  //
350  // Enable the usage fault interrupt.
351  //
352  HWREG(NVIC_SYS_HND_CTRL) |= NVIC_SYS_HND_CTRL_USAGE;
353  }
354  else if(ui32Interrupt == FAULT_SYSTICK)
355  {
356  //
357  // Enable the System Tick interrupt.
358  //
359  HWREG(NVIC_ST_CTRL) |= NVIC_ST_CTRL_INTEN;
360  }
361  else if((ui32Interrupt >= 16) && (ui32Interrupt <= 47))
362  {
363  //
364  // Enable the general interrupt.
365  //
366  HWREG(NVIC_EN0) = 1 << (ui32Interrupt - 16);
367  }
368  else if(ui32Interrupt >= 48)
369  {
370  //
371  // Enable the general interrupt.
372  //
373  HWREG(NVIC_EN1) = 1 << (ui32Interrupt - 48);
374  }
375 }
376 
377 //*****************************************************************************
378 //
380 //
381 //*****************************************************************************
382 void
383 IntDisable(uint32_t ui32Interrupt)
384 {
385  //
386  // Check the arguments.
387  //
388  ASSERT(ui32Interrupt < NUM_INTERRUPTS);
389 
390  //
391  // Determine the interrupt to disable.
392  //
393  if(ui32Interrupt == FAULT_MPU)
394  {
395  //
396  // Disable the MemManage interrupt.
397  //
398  HWREG(NVIC_SYS_HND_CTRL) &= ~(NVIC_SYS_HND_CTRL_MEM);
399  }
400  else if(ui32Interrupt == FAULT_BUS)
401  {
402  //
403  // Disable the bus fault interrupt.
404  //
405  HWREG(NVIC_SYS_HND_CTRL) &= ~(NVIC_SYS_HND_CTRL_BUS);
406  }
407  else if(ui32Interrupt == FAULT_USAGE)
408  {
409  //
410  // Disable the usage fault interrupt.
411  //
412  HWREG(NVIC_SYS_HND_CTRL) &= ~(NVIC_SYS_HND_CTRL_USAGE);
413  }
414  else if(ui32Interrupt == FAULT_SYSTICK)
415  {
416  //
417  // Disable the System Tick interrupt.
418  //
419  HWREG(NVIC_ST_CTRL) &= ~(NVIC_ST_CTRL_INTEN);
420  }
421  else if((ui32Interrupt >= 16) && (ui32Interrupt <= 47))
422  {
423  //
424  // Disable the general interrupt.
425  //
426  HWREG(NVIC_DIS0) = 1 << (ui32Interrupt - 16);
427  }
428  else if(ui32Interrupt >= 48)
429  {
430  //
431  // Disable the general interrupt.
432  //
433  HWREG(NVIC_DIS1) = 1 << (ui32Interrupt - 48);
434  }
435 }
436 
437 //*****************************************************************************
438 //
440 //
441 //*****************************************************************************
442 void
443 IntPendSet(uint32_t ui32Interrupt)
444 {
445  //
446  // Check the arguments.
447  //
448  ASSERT(ui32Interrupt < NUM_INTERRUPTS);
449 
450  //
451  // Determine the interrupt to pend.
452  //
453  if(ui32Interrupt == FAULT_NMI)
454  {
455  //
456  // Pend the NMI interrupt.
457  //
458  HWREG(NVIC_INT_CTRL) |= NVIC_INT_CTRL_NMI_SET;
459  }
460  else if(ui32Interrupt == FAULT_PENDSV)
461  {
462  //
463  // Pend the PendSV interrupt.
464  //
465  HWREG(NVIC_INT_CTRL) |= NVIC_INT_CTRL_PEND_SV;
466  }
467  else if(ui32Interrupt == FAULT_SYSTICK)
468  {
469  //
470  // Pend the SysTick interrupt.
471  //
472  HWREG(NVIC_INT_CTRL) |= NVIC_INT_CTRL_PENDSTSET;
473  }
474  else if((ui32Interrupt >= 16) && (ui32Interrupt <= 47))
475  {
476  //
477  // Pend the general interrupt.
478  //
479  HWREG(NVIC_PEND0) = 1 << (ui32Interrupt - 16);
480  }
481  else if(ui32Interrupt >= 48)
482  {
483  //
484  // Pend the general interrupt.
485  //
486  HWREG(NVIC_PEND1) = 1 << (ui32Interrupt - 48);
487  }
488 }
489 
490 //*****************************************************************************
491 //
493 //
494 //*****************************************************************************
495 bool
496 IntPendGet(uint32_t ui32Interrupt)
497 {
498  uint32_t ui32IntPending;
499 
500  //
501  // Check the arguments.
502  //
503  ASSERT(ui32Interrupt < NUM_INTERRUPTS);
504 
505  //
506  // Assume no interrupts are pending.
507  //
508  ui32IntPending = 0;
509 
510  //
511  // The lower 16 IRQ vectors are unsupported by this function
512  //
513  if (ui32Interrupt < 16)
514  {
515 
516  return 0;
517  }
518 
519  //
520  // Subtract lower 16 irq vectors
521  //
522  ui32Interrupt -= 16;
523 
524  //
525  // Check if the interrupt is pending
526  //
527  ui32IntPending = HWREG(NVIC_PEND0 + (ui32Interrupt / 32));
528  ui32IntPending &= (1 << (ui32Interrupt & 31));
529 
530  return ui32IntPending ? true : false;
531 }
532 
533 //*****************************************************************************
534 //
536 //
537 //*****************************************************************************
538 void
539 IntPendClear(uint32_t ui32Interrupt)
540 {
541  //
542  // Check the arguments.
543  //
544  ASSERT(ui32Interrupt < NUM_INTERRUPTS);
545 
546  //
547  // Determine the interrupt to unpend.
548  //
549  if(ui32Interrupt == FAULT_PENDSV)
550  {
551  //
552  // Unpend the PendSV interrupt.
553  //
554  HWREG(NVIC_INT_CTRL) |= NVIC_INT_CTRL_UNPEND_SV;
555  }
556  else if(ui32Interrupt == FAULT_SYSTICK)
557  {
558  //
559  // Unpend the SysTick interrupt.
560  //
561  HWREG(NVIC_INT_CTRL) |= NVIC_INT_CTRL_PENDSTCLR;
562  }
563  else if((ui32Interrupt >= 16) && (ui32Interrupt <= 47))
564  {
565  //
566  // Unpend the general interrupt.
567  //
568  HWREG(NVIC_UNPEND0) = 1 << (ui32Interrupt - 16);
569  }
570  else if(ui32Interrupt >= 48)
571  {
572  //
573  // Unpend the general interrupt.
574  //
575  HWREG(NVIC_UNPEND1) = 1 << (ui32Interrupt - 48);
576  }
577 }
int32_t IntPriorityGet(uint32_t ui32Interrupt)
Gets the priority of an interrupt.
Definition: interrupt.c:303
void(* g_pfnRAMVectors[NUM_INTERRUPTS])(void)
Definition: interrupt.c:141
void IntPendClear(uint32_t ui32Interrupt)
Unpends an interrupt.
Definition: interrupt.c:539
void IntPriorityGroupingSet(uint32_t ui32Bits)
Sets the priority grouping of the interrupt controller.
Definition: interrupt.c:224
#define ASSERT(expr)
Definition: debug.h:65
#define INT_PRI_LEVEL7
Definition: interrupt.h:115
uint32_t IntPriorityGroupingGet(void)
Gets the priority grouping of the interrupt controller.
Definition: interrupt.c:243
void IntPendSet(uint32_t ui32Interrupt)
Pends an interrupt.
Definition: interrupt.c:443
void IntUnregister(uint32_t ui32Interrupt)
Unregisters the function to be called when an interrupt occurs.
Definition: interrupt.c:205
void IntPrioritySet(uint32_t ui32Interrupt, uint8_t ui8Priority)
Sets the priority of an interrupt.
Definition: interrupt.c:278
bool IntPendGet(uint32_t ui32Interrupt)
Query whether an interrupt is pending.
Definition: interrupt.c:496
void IntDisable(uint32_t ui32Interrupt)
Disables an interrupt.
Definition: interrupt.c:383
void IntRegister(uint32_t ui32Interrupt, void(*pfnHandler)(void))
Registers a function to be called when an interrupt occurs.
Definition: interrupt.c:157
void IntEnable(uint32_t ui32Interrupt)
Enables an interrupt.
Definition: interrupt.c:323