interrupt.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  1. //*****************************************************************************
  2. //
  3. // interrupt.c - Driver for the NVIC Interrupt Controller.
  4. //
  5. // Copyright (c) 2005-2009 Luminary Micro, Inc. All rights reserved.
  6. // Software License Agreement
  7. //
  8. // Luminary Micro, Inc. (LMI) is supplying this software for use solely and
  9. // exclusively on LMI's microcontroller products.
  10. //
  11. // The software is owned by LMI and/or its suppliers, and is protected under
  12. // applicable copyright laws. All rights are reserved. You may not combine
  13. // this software with "viral" open-source software in order to form a larger
  14. // program. Any use in violation of the foregoing restrictions may subject
  15. // the user to criminal sanctions under applicable laws, as well as to civil
  16. // liability for the breach of the terms and conditions of this license.
  17. //
  18. // THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
  19. // OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
  20. // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
  21. // LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
  22. // CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
  23. //
  24. // This is part of revision 4694 of the Stellaris Peripheral Driver Library.
  25. //
  26. //*****************************************************************************
  27. //*****************************************************************************
  28. //
  29. //! \addtogroup interrupt_api
  30. //! @{
  31. //
  32. //*****************************************************************************
  33. #include "inc/hw_ints.h"
  34. #include "inc/hw_nvic.h"
  35. #include "inc/hw_types.h"
  36. #include "driverlib/cpu.h"
  37. #include "driverlib/debug.h"
  38. #include "driverlib/interrupt.h"
  39. //*****************************************************************************
  40. //
  41. // This is a mapping between priority grouping encodings and the number of
  42. // preemption priority bits.
  43. //
  44. //*****************************************************************************
  45. static const unsigned long g_pulPriority[] =
  46. {
  47. NVIC_APINT_PRIGROUP_0_8, NVIC_APINT_PRIGROUP_1_7, NVIC_APINT_PRIGROUP_2_6,
  48. NVIC_APINT_PRIGROUP_3_5, NVIC_APINT_PRIGROUP_4_4, NVIC_APINT_PRIGROUP_5_3,
  49. NVIC_APINT_PRIGROUP_6_2, NVIC_APINT_PRIGROUP_7_1
  50. };
  51. //*****************************************************************************
  52. //
  53. // This is a mapping between interrupt number and the register that contains
  54. // the priority encoding for that interrupt.
  55. //
  56. //*****************************************************************************
  57. static const unsigned long g_pulRegs[] =
  58. {
  59. 0, NVIC_SYS_PRI1, NVIC_SYS_PRI2, NVIC_SYS_PRI3, NVIC_PRI0, NVIC_PRI1,
  60. NVIC_PRI2, NVIC_PRI3, NVIC_PRI4, NVIC_PRI5, NVIC_PRI6, NVIC_PRI7,
  61. NVIC_PRI8, NVIC_PRI9, NVIC_PRI10, NVIC_PRI11, NVIC_PRI12, NVIC_PRI13
  62. };
  63. //*****************************************************************************
  64. //
  65. //! \internal
  66. //! The default interrupt handler.
  67. //!
  68. //! This is the default interrupt handler for all interrupts. It simply loops
  69. //! forever so that the system state is preserved for observation by a
  70. //! debugger. Since interrupts should be disabled before unregistering the
  71. //! corresponding handler, this should never be called.
  72. //!
  73. //! \return None.
  74. //
  75. //*****************************************************************************
  76. static void
  77. IntDefaultHandler(void)
  78. {
  79. //
  80. // Go into an infinite loop.
  81. //
  82. while(1)
  83. {
  84. }
  85. }
  86. //*****************************************************************************
  87. //
  88. // The processor vector table.
  89. //
  90. // This contains a list of the handlers for the various interrupt sources in
  91. // the system. The layout of this list is defined by the hardware; assertion
  92. // of an interrupt causes the processor to start executing directly at the
  93. // address given in the corresponding location in this list.
  94. //
  95. //*****************************************************************************
  96. #if defined(ewarm)
  97. static __no_init void (*g_pfnRAMVectors[NUM_INTERRUPTS])(void) @ "VTABLE";
  98. #elif defined(sourcerygxx)
  99. static __attribute__((section(".cs3.region-head.ram")))
  100. void (*g_pfnRAMVectors[NUM_INTERRUPTS])(void);
  101. #else
  102. static __attribute__((section("vtable")))
  103. void (*g_pfnRAMVectors[NUM_INTERRUPTS])(void);
  104. #endif
  105. //*****************************************************************************
  106. //
  107. //! Enables the processor interrupt.
  108. //!
  109. //! Allows the processor to respond to interrupts. This does not affect the
  110. //! set of interrupts enabled in the interrupt controller; it just gates the
  111. //! single interrupt from the controller to the processor.
  112. //!
  113. //! \note Previously, this function had no return value. As such, it was
  114. //! possible to include <tt>interrupt.h</tt> and call this function without
  115. //! having included <tt>hw_types.h</tt>. Now that the return is a
  116. //! <tt>tBoolean</tt>, a compiler error will occur in this case. The solution
  117. //! is to include <tt>hw_types.h</tt> before including <tt>interrupt.h</tt>.
  118. //!
  119. //! \return Returns \b true if interrupts were disabled when the function was
  120. //! called or \b false if they were initially enabled.
  121. //
  122. //*****************************************************************************
  123. tBoolean
  124. IntMasterEnable(void)
  125. {
  126. //
  127. // Enable processor interrupts.
  128. //
  129. return(CPUcpsie());
  130. }
  131. //*****************************************************************************
  132. //
  133. //! Disables the processor interrupt.
  134. //!
  135. //! Prevents the processor from receiving interrupts. This does not affect the
  136. //! set of interrupts enabled in the interrupt controller; it just gates the
  137. //! single interrupt from the controller to the processor.
  138. //!
  139. //! \note Previously, this function had no return value. As such, it was
  140. //! possible to include <tt>interrupt.h</tt> and call this function without
  141. //! having included <tt>hw_types.h</tt>. Now that the return is a
  142. //! <tt>tBoolean</tt>, a compiler error will occur in this case. The solution
  143. //! is to include <tt>hw_types.h</tt> before including <tt>interrupt.h</tt>.
  144. //!
  145. //! \return Returns \b true if interrupts were already disabled when the
  146. //! function was called or \b false if they were initially enabled.
  147. //
  148. //*****************************************************************************
  149. tBoolean
  150. IntMasterDisable(void)
  151. {
  152. //
  153. // Disable processor interrupts.
  154. //
  155. return(CPUcpsid());
  156. }
  157. //*****************************************************************************
  158. //
  159. //! Registers a function to be called when an interrupt occurs.
  160. //!
  161. //! \param ulInterrupt specifies the interrupt in question.
  162. //! \param pfnHandler is a pointer to the function to be called.
  163. //!
  164. //! This function is used to specify the handler function to be called when the
  165. //! given interrupt is asserted to the processor. When the interrupt occurs,
  166. //! if it is enabled (via IntEnable()), the handler function will be called in
  167. //! interrupt context. Since the handler function can preempt other code, care
  168. //! must be taken to protect memory or peripherals that are accessed by the
  169. //! handler and other non-handler code.
  170. //!
  171. //! \note The use of this function (directly or indirectly via a peripheral
  172. //! driver interrupt register function) moves the interrupt vector table from
  173. //! flash to SRAM. Therefore, care must be taken when linking the application
  174. //! to ensure that the SRAM vector table is located at the beginning of SRAM;
  175. //! otherwise NVIC will not look in the correct portion of memory for the
  176. //! vector table (it requires the vector table be on a 1 kB memory alignment).
  177. //! Normally, the SRAM vector table is so placed via the use of linker scripts;
  178. //! some tool chains, such as the evaluation version of RV-MDK, do not support
  179. //! linker scripts and therefore will not produce a valid executable. See the
  180. //! discussion of compile-time versus run-time interrupt handler registration
  181. //! in the introduction to this chapter.
  182. //!
  183. //! \return None.
  184. //
  185. //*****************************************************************************
  186. void
  187. IntRegister(unsigned long ulInterrupt, void (*pfnHandler)(void))
  188. {
  189. unsigned long ulIdx, ulValue;
  190. //
  191. // Check the arguments.
  192. //
  193. ASSERT(ulInterrupt < NUM_INTERRUPTS);
  194. //
  195. // Make sure that the RAM vector table is correctly aligned.
  196. //
  197. ASSERT(((unsigned long)g_pfnRAMVectors & 0x000003ff) == 0);
  198. //
  199. // See if the RAM vector table has been initialized.
  200. //
  201. if(HWREG(NVIC_VTABLE) != (unsigned long)g_pfnRAMVectors)
  202. {
  203. //
  204. // Copy the vector table from the beginning of FLASH to the RAM vector
  205. // table.
  206. //
  207. ulValue = HWREG(NVIC_VTABLE);
  208. for(ulIdx = 0; ulIdx < NUM_INTERRUPTS; ulIdx++)
  209. {
  210. g_pfnRAMVectors[ulIdx] = (void (*)(void))HWREG((ulIdx * 4) +
  211. ulValue);
  212. }
  213. //
  214. // Point NVIC at the RAM vector table.
  215. //
  216. HWREG(NVIC_VTABLE) = (unsigned long)g_pfnRAMVectors;
  217. }
  218. //
  219. // Save the interrupt handler.
  220. //
  221. g_pfnRAMVectors[ulInterrupt] = pfnHandler;
  222. }
  223. //*****************************************************************************
  224. //
  225. //! Unregisters the function to be called when an interrupt occurs.
  226. //!
  227. //! \param ulInterrupt specifies the interrupt in question.
  228. //!
  229. //! This function is used to indicate that no handler should be called when the
  230. //! given interrupt is asserted to the processor. The interrupt source will be
  231. //! automatically disabled (via IntDisable()) if necessary.
  232. //!
  233. //! \sa IntRegister() for important information about registering interrupt
  234. //! handlers.
  235. //!
  236. //! \return None.
  237. //
  238. //*****************************************************************************
  239. void
  240. IntUnregister(unsigned long ulInterrupt)
  241. {
  242. //
  243. // Check the arguments.
  244. //
  245. ASSERT(ulInterrupt < NUM_INTERRUPTS);
  246. //
  247. // Reset the interrupt handler.
  248. //
  249. g_pfnRAMVectors[ulInterrupt] = IntDefaultHandler;
  250. }
  251. //*****************************************************************************
  252. //
  253. //! Sets the priority grouping of the interrupt controller.
  254. //!
  255. //! \param ulBits specifies the number of bits of preemptable priority.
  256. //!
  257. //! This function specifies the split between preemptable priority levels and
  258. //! subpriority levels in the interrupt priority specification. The range of
  259. //! the grouping values are dependent upon the hardware implementation; on
  260. //! the Stellaris family, three bits are available for hardware interrupt
  261. //! prioritization and therefore priority grouping values of three through
  262. //! seven have the same effect.
  263. //!
  264. //! \return None.
  265. //
  266. //*****************************************************************************
  267. void
  268. IntPriorityGroupingSet(unsigned long ulBits)
  269. {
  270. //
  271. // Check the arguments.
  272. //
  273. ASSERT(ulBits < NUM_PRIORITY);
  274. //
  275. // Set the priority grouping.
  276. //
  277. HWREG(NVIC_APINT) = NVIC_APINT_VECTKEY | g_pulPriority[ulBits];
  278. }
  279. //*****************************************************************************
  280. //
  281. //! Gets the priority grouping of the interrupt controller.
  282. //!
  283. //! This function returns the split between preemptable priority levels and
  284. //! subpriority levels in the interrupt priority specification.
  285. //!
  286. //! \return The number of bits of preemptable priority.
  287. //
  288. //*****************************************************************************
  289. unsigned long
  290. IntPriorityGroupingGet(void)
  291. {
  292. unsigned long ulLoop, ulValue;
  293. //
  294. // Read the priority grouping.
  295. //
  296. ulValue = HWREG(NVIC_APINT) & NVIC_APINT_PRIGROUP_M;
  297. //
  298. // Loop through the priority grouping values.
  299. //
  300. for(ulLoop = 0; ulLoop < NUM_PRIORITY; ulLoop++)
  301. {
  302. //
  303. // Stop looping if this value matches.
  304. //
  305. if(ulValue == g_pulPriority[ulLoop])
  306. {
  307. break;
  308. }
  309. }
  310. //
  311. // Return the number of priority bits.
  312. //
  313. return(ulLoop);
  314. }
  315. //*****************************************************************************
  316. //
  317. //! Sets the priority of an interrupt.
  318. //!
  319. //! \param ulInterrupt specifies the interrupt in question.
  320. //! \param ucPriority specifies the priority of the interrupt.
  321. //!
  322. //! This function is used to set the priority of an interrupt. When multiple
  323. //! interrupts are asserted simultaneously, the ones with the highest priority
  324. //! are processed before the lower priority interrupts. Smaller numbers
  325. //! correspond to higher interrupt priorities; priority 0 is the highest
  326. //! interrupt priority.
  327. //!
  328. //! The hardware priority mechanism will only look at the upper N bits of the
  329. //! priority level (where N is 3 for the Stellaris family), so any
  330. //! prioritization must be performed in those bits. The remaining bits can be
  331. //! used to sub-prioritize the interrupt sources, and may be used by the
  332. //! hardware priority mechanism on a future part. This arrangement allows
  333. //! priorities to migrate to different NVIC implementations without changing
  334. //! the gross prioritization of the interrupts.
  335. //!
  336. //! \return None.
  337. //
  338. //*****************************************************************************
  339. void
  340. IntPrioritySet(unsigned long ulInterrupt, unsigned char ucPriority)
  341. {
  342. unsigned long ulTemp;
  343. //
  344. // Check the arguments.
  345. //
  346. ASSERT((ulInterrupt >= 4) && (ulInterrupt < NUM_INTERRUPTS));
  347. //
  348. // Set the interrupt priority.
  349. //
  350. ulTemp = HWREG(g_pulRegs[ulInterrupt >> 2]);
  351. ulTemp &= ~(0xFF << (8 * (ulInterrupt & 3)));
  352. ulTemp |= ucPriority << (8 * (ulInterrupt & 3));
  353. HWREG(g_pulRegs[ulInterrupt >> 2]) = ulTemp;
  354. }
  355. //*****************************************************************************
  356. //
  357. //! Gets the priority of an interrupt.
  358. //!
  359. //! \param ulInterrupt specifies the interrupt in question.
  360. //!
  361. //! This function gets the priority of an interrupt. See IntPrioritySet() for
  362. //! a definition of the priority value.
  363. //!
  364. //! \return Returns the interrupt priority, or -1 if an invalid interrupt was
  365. //! specified.
  366. //
  367. //*****************************************************************************
  368. long
  369. IntPriorityGet(unsigned long ulInterrupt)
  370. {
  371. //
  372. // Check the arguments.
  373. //
  374. ASSERT((ulInterrupt >= 4) && (ulInterrupt < NUM_INTERRUPTS));
  375. //
  376. // Return the interrupt priority.
  377. //
  378. return((HWREG(g_pulRegs[ulInterrupt >> 2]) >> (8 * (ulInterrupt & 3))) &
  379. 0xFF);
  380. }
  381. //*****************************************************************************
  382. //
  383. //! Enables an interrupt.
  384. //!
  385. //! \param ulInterrupt specifies the interrupt to be enabled.
  386. //!
  387. //! The specified interrupt is enabled in the interrupt controller. Other
  388. //! enables for the interrupt (such as at the peripheral level) are unaffected
  389. //! by this function.
  390. //!
  391. //! \return None.
  392. //
  393. //*****************************************************************************
  394. void
  395. IntEnable(unsigned long ulInterrupt)
  396. {
  397. //
  398. // Check the arguments.
  399. //
  400. ASSERT(ulInterrupt < NUM_INTERRUPTS);
  401. //
  402. // Determine the interrupt to enable.
  403. //
  404. if(ulInterrupt == FAULT_MPU)
  405. {
  406. //
  407. // Enable the MemManage interrupt.
  408. //
  409. HWREG(NVIC_SYS_HND_CTRL) |= NVIC_SYS_HND_CTRL_MEM;
  410. }
  411. else if(ulInterrupt == FAULT_BUS)
  412. {
  413. //
  414. // Enable the bus fault interrupt.
  415. //
  416. HWREG(NVIC_SYS_HND_CTRL) |= NVIC_SYS_HND_CTRL_BUS;
  417. }
  418. else if(ulInterrupt == FAULT_USAGE)
  419. {
  420. //
  421. // Enable the usage fault interrupt.
  422. //
  423. HWREG(NVIC_SYS_HND_CTRL) |= NVIC_SYS_HND_CTRL_USAGE;
  424. }
  425. else if(ulInterrupt == FAULT_SYSTICK)
  426. {
  427. //
  428. // Enable the System Tick interrupt.
  429. //
  430. HWREG(NVIC_ST_CTRL) |= NVIC_ST_CTRL_INTEN;
  431. }
  432. else if((ulInterrupt >= 16) && (ulInterrupt <= 47))
  433. {
  434. //
  435. // Enable the general interrupt.
  436. //
  437. HWREG(NVIC_EN0) = 1 << (ulInterrupt - 16);
  438. }
  439. else if(ulInterrupt >= 48)
  440. {
  441. //
  442. // Enable the general interrupt.
  443. //
  444. HWREG(NVIC_EN1) = 1 << (ulInterrupt - 48);
  445. }
  446. }
  447. //*****************************************************************************
  448. //
  449. //! Disables an interrupt.
  450. //!
  451. //! \param ulInterrupt specifies the interrupt to be disabled.
  452. //!
  453. //! The specified interrupt is disabled in the interrupt controller. Other
  454. //! enables for the interrupt (such as at the peripheral level) are unaffected
  455. //! by this function.
  456. //!
  457. //! \return None.
  458. //
  459. //*****************************************************************************
  460. void
  461. IntDisable(unsigned long ulInterrupt)
  462. {
  463. //
  464. // Check the arguments.
  465. //
  466. ASSERT(ulInterrupt < NUM_INTERRUPTS);
  467. //
  468. // Determine the interrupt to disable.
  469. //
  470. if(ulInterrupt == FAULT_MPU)
  471. {
  472. //
  473. // Disable the MemManage interrupt.
  474. //
  475. HWREG(NVIC_SYS_HND_CTRL) &= ~(NVIC_SYS_HND_CTRL_MEM);
  476. }
  477. else if(ulInterrupt == FAULT_BUS)
  478. {
  479. //
  480. // Disable the bus fault interrupt.
  481. //
  482. HWREG(NVIC_SYS_HND_CTRL) &= ~(NVIC_SYS_HND_CTRL_BUS);
  483. }
  484. else if(ulInterrupt == FAULT_USAGE)
  485. {
  486. //
  487. // Disable the usage fault interrupt.
  488. //
  489. HWREG(NVIC_SYS_HND_CTRL) &= ~(NVIC_SYS_HND_CTRL_USAGE);
  490. }
  491. else if(ulInterrupt == FAULT_SYSTICK)
  492. {
  493. //
  494. // Disable the System Tick interrupt.
  495. //
  496. HWREG(NVIC_ST_CTRL) &= ~(NVIC_ST_CTRL_INTEN);
  497. }
  498. else if((ulInterrupt >= 16) && (ulInterrupt <= 47))
  499. {
  500. //
  501. // Disable the general interrupt.
  502. //
  503. HWREG(NVIC_DIS0) = 1 << (ulInterrupt - 16);
  504. }
  505. else if(ulInterrupt >= 48)
  506. {
  507. //
  508. // Disable the general interrupt.
  509. //
  510. HWREG(NVIC_DIS1) = 1 << (ulInterrupt - 48);
  511. }
  512. }
  513. //*****************************************************************************
  514. //
  515. // Close the Doxygen group.
  516. //! @}
  517. //
  518. //*****************************************************************************