ihndlr.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. /* This source file is part of the ATMEL AVR-UC3-SoftwareFramework-2.8.1 Release */
  2. /**
  3. * \file
  4. *
  5. * \brief INTC software driver for AVR UC3 devices.
  6. *
  7. * Copyright (C) 2009 - 2011 Atmel Corporation. All rights reserved.
  8. *
  9. * \page License
  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. The name of Atmel may not be used to endorse or promote products derived
  22. * from this software without specific prior written permission.
  23. *
  24. * 4. This software may only be redistributed and used in connection with an
  25. * Atmel AVR product.
  26. *
  27. * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
  28. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  29. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
  30. * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
  31. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  32. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  33. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  34. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  35. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  36. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  37. * DAMAGE.
  38. */
  39. #include <arch/avr32.h>
  40. #include <dev/irqreg.h>
  41. #include <avr32/io.h>
  42. #include <arch/avr32/preprocessor.h>
  43. /**************************** Added for NutOS ****************************/
  44. //! Maximum number of interrupt request lines per group.
  45. #define AVR32_INTC_MAX_NUM_IRQS_PER_GRP 32
  46. //! Number of interrupt priority levels.
  47. #define AVR32_INTC_NUM_INT_LEVELS (1 << AVR32_INTC_IPR_INTLEVEL_SIZE)
  48. //! Pointer to interrupt handler.
  49. typedef void (*__int_handler)(void);
  50. #define Max(a, b) (((a) > (b)) ? (a) : (b))
  51. /*************************************************************************/
  52. /**
  53. * \internal
  54. * \brief Import the _evba symbol from exception.S
  55. */
  56. extern void _evba;
  57. /**
  58. * \internal
  59. * \brief Import the symbols _int0, _int1, _int2, _int3 defined in exception.S
  60. */
  61. extern void _int0, _int1, _int2, _int3;
  62. /**
  63. * \internal
  64. * \brief Values to store in the interrupt priority registers for the various
  65. * interrupt priority levels.
  66. */
  67. #define IPR_INT0 ((AVR32_INTC_INT0 << AVR32_INTC_IPR_INTLEVEL_OFFSET) \
  68. | ((int)&_int0 - (int)&_evba))
  69. #define IPR_INT1 ((AVR32_INTC_INT1 << AVR32_INTC_IPR_INTLEVEL_OFFSET) \
  70. | ((int)&_int1 - (int)&_evba))
  71. #define IPR_INT2 ((AVR32_INTC_INT2 << AVR32_INTC_IPR_INTLEVEL_OFFSET) \
  72. | ((int)&_int2 - (int)&_evba))
  73. #define IPR_INT3 ((AVR32_INTC_INT3 << AVR32_INTC_IPR_INTLEVEL_OFFSET) \
  74. | ((int)&_int3 - (int)&_evba))
  75. /**
  76. * \internal
  77. * \brief Table of interrupt line handlers per interrupt group in order to
  78. * optimize RAM space. Each line handler table contains a set of pointers to
  79. * interrupt handlers.
  80. */
  81. #if (defined __GNUC__)
  82. # define DECL_INT_LINE_HANDLER_TABLE(GRP, unused) \
  83. static volatile __int_handler \
  84. _int_line_handler_table_##GRP[Max(AVR32_INTC_NUM_IRQS_PER_GRP##GRP, 1)];
  85. #elif (defined __ICCAVR32__)
  86. # define DECL_INT_LINE_HANDLER_TABLE(GRP, unused) \
  87. static volatile __no_init __int_handler \
  88. _int_line_handler_table_##GRP[Max(AVR32_INTC_NUM_IRQS_PER_GRP##GRP, 1)];
  89. #endif
  90. MREPEAT(AVR32_INTC_NUM_INT_GRPS, DECL_INT_LINE_HANDLER_TABLE, ~);
  91. #undef DECL_INT_LINE_HANDLER_TABLE
  92. /**
  93. * \internal
  94. * \brief Table containing for each interrupt group the number of interrupt
  95. * request lines and a pointer to the table of interrupt line handlers.
  96. */
  97. static const struct
  98. {
  99. unsigned int num_irqs;
  100. volatile __int_handler *_int_line_handler_table;
  101. } _int_handler_table[AVR32_INTC_NUM_INT_GRPS] =
  102. {
  103. #define INSERT_INT_LINE_HANDLER_TABLE(GRP, unused) \
  104. {AVR32_INTC_NUM_IRQS_PER_GRP##GRP, _int_line_handler_table_##GRP},
  105. MREPEAT(AVR32_INTC_NUM_INT_GRPS, INSERT_INT_LINE_HANDLER_TABLE, ~)
  106. #undef INSERT_INT_LINE_HANDLER_TABLE
  107. };
  108. /**
  109. * \internal
  110. * \brief Default interrupt handler.
  111. */
  112. #if (defined __GNUC__)
  113. __attribute__((__interrupt__))
  114. #elif (defined __ICCAVR32__)
  115. __interrupt
  116. #endif
  117. static void _unhandled_interrupt(void)
  118. {
  119. // Catch unregistered interrupts.
  120. //while (1);
  121. }
  122. /**
  123. * \brief Gets the interrupt handler of the current event at the \a int_level
  124. * interrupt priority level (called from exception.S).
  125. *
  126. * \param int_level Interrupt priority level to handle.
  127. *
  128. * \return Interrupt handler to execute.
  129. */
  130. __int_handler _get_interrupt_handler(uint32_t int_level);
  131. __int_handler _get_interrupt_handler(uint32_t int_level)
  132. {
  133. /* ICR3 is mapped first, ICR0 last.
  134. Code in exception.S puts int_level in R12 which is used by the compiler
  135. to pass a single argument to a function. */
  136. uint32_t int_grp = AVR32_INTC.icr[AVR32_INTC_INT3 - int_level];
  137. uint32_t int_req = AVR32_INTC.irr[int_grp];
  138. /* As an interrupt may disappear while it is being fetched by the CPU
  139. (spurious interrupt caused by a delayed response from an MCU peripheral
  140. to an interrupt flag clear or interrupt disable instruction), check if
  141. there are remaining interrupt lines to process.
  142. If a spurious interrupt occurs, the status register (SR) contains an
  143. execution mode and interrupt level masks corresponding to a level 0
  144. interrupt, whatever the interrupt priority level causing the spurious
  145. event. This behavior has been chosen because a spurious interrupt has
  146. not to be a priority one and because it may not cause any trouble to
  147. other interrupts.
  148. However, these spurious interrupts place the hardware in an unstable
  149. state and could give problems in other/future versions of the CPU, so
  150. the software has to be written so that they never occur. The only safe
  151. way of achieving this is to always clear or disable peripheral
  152. interrupts with the following sequence:
  153. 1: Mask the interrupt in the CPU by setting GM (or IxM) in SR.
  154. 2: Perform the bus access to the peripheral register that clears or
  155. disables the interrupt.
  156. 3: Wait until the interrupt has actually been cleared or disabled by the
  157. peripheral. This is usually performed by reading from a register in the
  158. same peripheral (it DOES NOT have to be the same register that was
  159. accessed in step 2, but it MUST be in the same peripheral), what takes
  160. bus system latencies into account, but peripheral internal latencies
  161. (generally 0 cycle) also have to be considered.
  162. 4: Unmask the interrupt in the CPU by clearing GM (or IxM) in SR.
  163. Note that steps 1 and 4 are useless inside interrupt handlers as the
  164. corresponding interrupt level is automatically masked by IxM (unless IxM
  165. is explicitly cleared by the software).*/
  166. /* Get the right IRQ handler.
  167. If several interrupt lines are active in the group, the interrupt line
  168. with the highest number is selected. This is to be coherent with the
  169. prioritization of interrupt groups performed by the hardware interrupt
  170. controller.
  171. If no handler has been registered for the pending interrupt,
  172. _unhandled_interrupt will be selected thanks to the initialization of
  173. _int_line_handler_table_x by INTC_init_interrupts.
  174. exception.S will provide the interrupt handler with a clean interrupt
  175. stack frame, with nothing more pushed onto the stack. The interrupt
  176. handler must manage the `rete' instruction, which can be done using
  177. pure assembly, inline assembly or the `__attribute__((__interrupt__))'
  178. C function attribute.*/
  179. return (int_req)
  180. ? _int_handler_table[int_grp]._int_line_handler_table[32
  181. - __builtin_clz(int_req) - 1]
  182. : NULL;
  183. }
  184. /**
  185. * \internal
  186. * \brief Init EVBA address. This operation may or may not have been done by the
  187. * C startup process.
  188. */
  189. static __inline__ void INTC_init_evba(void)
  190. {
  191. Set_system_register(AVR32_EVBA, (int32_t)&_evba );
  192. }
  193. /**
  194. * \brief Initializes the hardware interrupt controller driver.
  195. *
  196. */
  197. void init_interrupts(void)
  198. {
  199. uint32_t int_grp, int_req;
  200. INTC_init_evba();
  201. // For all interrupt groups,
  202. for (int_grp = 0; int_grp < AVR32_INTC_NUM_INT_GRPS; int_grp++)
  203. {
  204. // For all interrupt request lines of each group,
  205. for (int_req = 0;
  206. int_req < _int_handler_table[int_grp].num_irqs;
  207. int_req++)
  208. {
  209. /* Assign _unhandled_interrupt as the default interrupt
  210. handler. */
  211. _int_handler_table[int_grp]
  212. ._int_line_handler_table[int_req]
  213. = &_unhandled_interrupt;
  214. }
  215. /* Set the interrupt group priority register to its default
  216. value.
  217. By default, all interrupt groups are linked to the interrupt
  218. priority level 0 and to the interrupt vector _int0. */
  219. AVR32_INTC.ipr[int_grp] = IPR_INT0;
  220. }
  221. }
  222. /**
  223. * \brief Registers an interrupt handler.
  224. *
  225. * \param handler Interrupt handler to register.
  226. * \param irq IRQ of the interrupt handler to register.
  227. * \param int_level Interrupt priority level to assign to the group of this IRQ.
  228. *
  229. * \warning The interrupt handler must manage the `rete' instruction, which can
  230. * be done using pure assembly, inline assembly or the
  231. * `__attribute__((__interrupt__))' C function attribute.
  232. *
  233. * \warning If several interrupt handlers of a same group are registered with
  234. * different priority levels, only the latest priority level set will
  235. * be effective.
  236. *
  237. */
  238. void register_interrupt(__int_handler handler, uint32_t irq, uint32_t int_level)
  239. {
  240. // Determine the group of the IRQ.
  241. uint32_t int_grp = irq / AVR32_INTC_MAX_NUM_IRQS_PER_GRP;
  242. /* Store in _int_line_handler_table_x the pointer to the interrupt
  243. handler, so that _get_interrupt_handler can retrieve it when the
  244. interrupt is vectored. */
  245. _int_handler_table[int_grp]
  246. ._int_line_handler_table[irq % AVR32_INTC_MAX_NUM_IRQS_PER_GRP]
  247. = handler;
  248. /* Program the corresponding IPRX register to set the interrupt priority
  249. level and the interrupt vector offset that will be fetched by the core
  250. interrupt system.
  251. NOTE: The _intx functions are intermediate assembly functions between
  252. the core interrupt system and the user interrupt handler. */
  253. if (int_level == AVR32_INTC_INT0) {
  254. AVR32_INTC.ipr[int_grp] = IPR_INT0;
  255. } else if (int_level == AVR32_INTC_INT1) {
  256. AVR32_INTC.ipr[int_grp] = IPR_INT1;
  257. } else if (int_level == AVR32_INTC_INT2) {
  258. AVR32_INTC.ipr[int_grp] = IPR_INT2;
  259. } else {
  260. AVR32_INTC.ipr[int_grp] = IPR_INT3;
  261. }
  262. }