interrupt_avr32.h 11 KB

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