interrupt_avr32.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. /**
  2. * \file
  3. *
  4. * \brief Global interrupt management for 32-bit AVR
  5. *
  6. * Copyright (c) 2010-2016 Atmel Corporation. All rights reserved.
  7. *
  8. * \asf_license_start
  9. *
  10. * \page License
  11. *
  12. * Redistribution and use in source and binary forms, with or without
  13. * modification, are permitted provided that the following conditions are met:
  14. *
  15. * 1. Redistributions of source code must retain the above copyright notice,
  16. * this list of conditions and the following disclaimer.
  17. *
  18. * 2. Redistributions in binary form must reproduce the above copyright notice,
  19. * this list of conditions and the following disclaimer in the documentation
  20. * and/or other materials provided with the distribution.
  21. *
  22. * 3. The name of Atmel may not be used to endorse or promote products derived
  23. * from this software without specific prior written permission.
  24. *
  25. * 4. This software may only be redistributed and used in connection with an
  26. * Atmel microcontroller product.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
  29. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  30. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
  31. * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
  32. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  33. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  34. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  36. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  37. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  38. * POSSIBILITY OF SUCH DAMAGE.
  39. *
  40. * \asf_license_stop
  41. *
  42. */
  43. /*
  44. * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
  45. */
  46. #ifndef UTILS_INTERRUPT_INTERRUPT_H
  47. #define UTILS_INTERRUPT_INTERRUPT_H
  48. #include <compiler.h>
  49. #include <preprocessor/tpaste.h>
  50. /**
  51. * \weakgroup interrupt_group
  52. *
  53. * @{
  54. */
  55. //! Pointer to interrupt handler.
  56. #if (defined __GNUC__)
  57. typedef void (*__int_handler)(void);
  58. #elif (defined __ICCAVR32__)
  59. typedef void (__interrupt *__int_handler)(void);
  60. #endif
  61. /**
  62. * \name Interrupt Service Routine definition and registration
  63. *
  64. * @{
  65. */
  66. #if defined(__GNUC__) || defined(__DOXYGEN__)
  67. /**
  68. * \brief Macro to declare an interrupt service routine
  69. *
  70. * With GCC, this macro only causes the function to be defined as an interrupt
  71. * service routine, i.e., it does not add any initialization code. A valid
  72. * function name is required for use with \ref irq_register_handler.
  73. *
  74. * With IAR, this macro defines the function as an interrupt service routine and
  75. * causes the compiler to add initialization code for the interrupt controller
  76. * (INTC). The interrupt group and level, as well as a valid function name are
  77. * therefore required.\n
  78. * \note If \ref CONFIG_INTERRUPT_FORCE_INTC is defined, only a valid function
  79. * name is required for use with \ref irq_register_handler. The initialization
  80. * code will be handled by the interrupt controller itself.
  81. *
  82. * Usage:
  83. * \code
  84. ISR(foo_irq_handler, AVR32_xxx_IRQ_GROUP, n)
  85. {
  86. // Function definition
  87. ...
  88. }
  89. \endcode
  90. *
  91. * \param func Name for the function, needed by \ref irq_register_handler.
  92. * \param int_grp Interrupt group to define service routine for.
  93. * \param int_lvl Priority level to set for the interrupt group, in the range
  94. * \c 0 to \c 3.
  95. *
  96. * \note The interrupt groups can be found in the device header files for the
  97. * IAR toolchain (avr32/io\<part\>.h).
  98. *
  99. * \todo Update to use IRQ numbers when these are made available in the
  100. * device header files of both IAR and GCC.
  101. */
  102. # define ISR(func, int_grp, int_lvl) \
  103. __attribute__((__interrupt__)) static void func (void)
  104. #elif defined(__ICCAVR32__) && defined(CONFIG_INTERRUPT_FORCE_INTC)
  105. # define ISR(func, int_grp, int_lvl) \
  106. __interrupt static void func (void)
  107. #elif defined(__ICCAVR32__)
  108. # define ISR0(...) _Pragma(#__VA_ARGS__)
  109. # define ISR(func, int_grp, int_lvl) \
  110. ISR0(handler=int_grp, int_lvl) \
  111. __interrupt static void func (void)
  112. #endif
  113. #if defined(__GNUC__) || defined(__DOXYGEN__) || defined(CONFIG_INTERRUPT_FORCE_INTC)
  114. # include <intc.h>
  115. /**
  116. * \brief Initialize interrupt vectors
  117. *
  118. * With GCC, this macro adds code for initialization of the interrupt vectors
  119. * with the driver for the interrupt controller (INTC).
  120. *
  121. * With IAR and unless \ref CONFIG_INTERRUPT_FORCE_INTC is defined this macro
  122. * adds no code, since initialization of the INTC is handled by the compiler.
  123. * \note Defining \ref CONFIG_INTERRUPT_FORCE_INTC will force the use of the
  124. * INTC driver, replacing the compiler built-in interrupt handler.
  125. *
  126. * This must be called prior to \ref irq_register_handler.
  127. */
  128. # define irq_initialize_vectors() INTC_init_interrupts()
  129. /**
  130. * \brief Register handler for interrupt
  131. *
  132. * With GCC, this macro adds code for registering an interrupt handler with the
  133. * driver for the interrupt controller (INTC).
  134. *
  135. * With IAR and unless \ref CONFIG_INTERRUPT_FORCE_INTC is defined this macro
  136. * adds no code, since initialization of the INTC is handled by the compiler.
  137. * \note Defining \ref CONFIG_INTERRUPT_FORCE_INTC will force the use of the
  138. * INTC driver, replacing the compiler built-in interrupt handler.
  139. *
  140. * \param func Name of handler function to register for interrupt.
  141. * \param int_num Number of the interrupt line to register function for.
  142. * \param int_lvl Priority level to set for the interrupt's group, in the range
  143. * \c 0 to \c 3.
  144. *
  145. * Usage:
  146. * \code
  147. irq_initialize_vectors();
  148. irq_register_handler(foo_irq_handler, AVR32_xxx_IRQ, n);
  149. \endcode
  150. *
  151. * \note The function \a func must be defined with the \ref ISR macro.
  152. * \note The interrupt line number can be found in the device header files for
  153. * the GCC toolchain (avr32/\<part\>.h).
  154. */
  155. # define irq_register_handler(func, int_num, int_lvl) \
  156. INTC_register_interrupt(func, int_num, \
  157. TPASTE2(AVR32_INTC_INT, int_lvl))
  158. #elif defined(__ICCAVR32__)
  159. # define irq_initialize_vectors() do{ } while(0)
  160. # define irq_register_handler(func, int_num, int_lvl) do{ } while(0)
  161. #endif
  162. //@}
  163. #if (defined __GNUC__)
  164. # define cpu_irq_enable() \
  165. do { \
  166. barrier(); \
  167. __builtin_csrf(AVR32_SR_GM_OFFSET); \
  168. } while (0)
  169. # define cpu_irq_disable() \
  170. do { \
  171. __builtin_ssrf(AVR32_SR_GM_OFFSET); \
  172. barrier(); \
  173. } while (0)
  174. #elif (defined __ICCAVR32__)
  175. # if (defined CONFIG_INTERRUPT_FORCE_INTC)
  176. # define cpu_irq_enable() \
  177. do { \
  178. barrier(); \
  179. __clear_status_flag(AVR32_SR_GM_OFFSET); \
  180. } while(0)
  181. # define cpu_irq_disable() \
  182. do { \
  183. __set_status_flag(AVR32_SR_GM_OFFSET); \
  184. barrier(); \
  185. } while (0)
  186. # else
  187. # define cpu_irq_enable() __enable_interrupt()
  188. # define cpu_irq_disable() __disable_interrupt()
  189. # endif
  190. #endif
  191. typedef uint32_t irqflags_t;
  192. static inline irqflags_t cpu_irq_save(void)
  193. {
  194. volatile irqflags_t flags;
  195. flags = sysreg_read(AVR32_SR);
  196. cpu_irq_disable();
  197. return flags;
  198. }
  199. static inline bool cpu_irq_is_enabled_flags(irqflags_t flags)
  200. {
  201. return !(flags & AVR32_SR_GM_MASK);
  202. }
  203. static inline void cpu_irq_restore(irqflags_t flags)
  204. {
  205. barrier();
  206. /* Restore the global IRQ mask status flag if it was previously set */
  207. if ( cpu_irq_is_enabled_flags(flags) ) {
  208. cpu_irq_enable();
  209. }
  210. barrier();
  211. }
  212. #define cpu_irq_is_enabled() cpu_irq_is_enabled_flags(sysreg_read(AVR32_SR))
  213. //! \name Global interrupt levels
  214. //@{
  215. /**
  216. * \brief Check if interrupt level is enabled in supplied flags
  217. *
  218. * \param flags State of interrupt flags.
  219. * \param level Bit position for interrupt level.
  220. *
  221. * \return True if interrupt level is enabled.
  222. */
  223. static inline bool cpu_irq_level_is_enabled_flags(irqflags_t flags,
  224. uint32_t level)
  225. {
  226. return !(flags & (1 << level));
  227. }
  228. /**
  229. * \brief Check if interrupt level is enabled
  230. *
  231. * \param level Interrupt level (0 to 3).
  232. *
  233. * \return True if interrupt level \a level is enabled.
  234. *
  235. * \note The interrupt level must be known at compile time.
  236. */
  237. #define cpu_irq_level_is_enabled(level) \
  238. cpu_irq_level_is_enabled_flags(sysreg_read(AVR32_SR), \
  239. TPASTE3(AVR32_SR_I, level, M_OFFSET))
  240. #if defined(__GNUC__) || defined(__DOXYGEN__)
  241. /**
  242. * \brief Enable interrupt level
  243. *
  244. * \param level Interrupt level to enable (0 to 3).
  245. *
  246. * \note The interrupt level must be known at compile time.
  247. */
  248. # define cpu_irq_enable_level(level) \
  249. do { \
  250. barrier(); \
  251. __builtin_csrf(TPASTE3(AVR32_SR_I, level, M_OFFSET)); \
  252. } while (0)
  253. /**
  254. * \brief Disable interrupt level
  255. *
  256. * \param level Interrupt level to disable (0 to 3).
  257. *
  258. * \note The interrupt level must be known at compile time.
  259. */
  260. # define cpu_irq_disable_level(level) \
  261. do { \
  262. __builtin_ssrf(TPASTE3(AVR32_SR_I, level, M_OFFSET)); \
  263. barrier(); \
  264. } while (0)
  265. #elif (defined __ICCAVR32__)
  266. # define cpu_irq_enable_level(level) \
  267. do { \
  268. barrier(); \
  269. __clear_status_flag(TPASTE3(AVR32_SR_I, level, M_OFFSET)); \
  270. } while(0)
  271. # define cpu_irq_disable_level(level) \
  272. do { \
  273. __set_status_flag(TPASTE3(AVR32_SR_I, level, M_OFFSET)); \
  274. barrier(); \
  275. } while (0)
  276. #endif
  277. //@}
  278. //@}
  279. /**
  280. * \weakgroup interrupt_deprecated_group
  281. * @{
  282. */
  283. #define Enable_global_interrupt() cpu_irq_enable()
  284. #define Disable_global_interrupt() cpu_irq_disable()
  285. #define Is_global_interrupt_enabled() cpu_irq_is_enabled()
  286. #define Enable_interrupt_level(level) cpu_irq_enable_level(level)
  287. #define Disable_interrupt_level(level) cpu_irq_disable_level(level)
  288. #define Is_interrupt_level_enabled(level) cpu_irq_level_is_enabled(level)
  289. /**
  290. * \name Interrupt protection of code sections
  291. * \note Use \ref cpu_irq_save and \ref cpu_irq_restore instead of these macros.
  292. * @{
  293. */
  294. /**
  295. * \brief Start section with code protected against interrupts
  296. */
  297. #define AVR32_ENTER_CRITICAL_REGION() \
  298. { \
  299. bool global_interrupt_enabled = Is_global_interrupt_enabled(); \
  300. Disable_global_interrupt();
  301. /**
  302. * \brief End section with code protected against interrupts
  303. *
  304. * \note This macro must always be used in conjunction with
  305. * \ref AVR32_ENTER_CRITICAL_REGION so that interrupts are enabled again.
  306. */
  307. #define AVR32_LEAVE_CRITICAL_REGION() \
  308. if (global_interrupt_enabled) Enable_global_interrupt(); \
  309. }
  310. //@}
  311. //@}
  312. #endif /* UTILS_INTERRUPT_INTERRUPT_H */