irq.h 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. /*
  2. * Copyright (c) 2013-2014 Wind River Systems, Inc.
  3. * Copyright (c) 2019 Nordic Semiconductor ASA.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0
  6. */
  7. /**
  8. * @file
  9. * @brief ARM AArch32 public interrupt handling
  10. *
  11. * ARM AArch32-specific kernel interrupt handling interface. Included by
  12. * arm/arch.h.
  13. */
  14. #ifndef ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_IRQ_H_
  15. #define ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_IRQ_H_
  16. #include <irq.h>
  17. #include <sw_isr_table.h>
  18. #include <stdbool.h>
  19. #ifdef __cplusplus
  20. extern "C" {
  21. #endif
  22. #ifdef _ASMLANGUAGE
  23. GTEXT(z_arm_int_exit);
  24. GTEXT(arch_irq_enable)
  25. GTEXT(arch_irq_disable)
  26. GTEXT(arch_irq_is_enabled)
  27. #if defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER)
  28. GTEXT(z_soc_irq_get_active)
  29. GTEXT(z_soc_irq_eoi)
  30. #endif /* CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */
  31. #else
  32. #if !defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER)
  33. extern void arch_irq_enable(unsigned int irq);
  34. extern void arch_irq_disable(unsigned int irq);
  35. extern int arch_irq_is_enabled(unsigned int irq);
  36. /* internal routine documented in C file, needed by IRQ_CONNECT() macro */
  37. extern void z_arm_irq_priority_set(unsigned int irq, unsigned int prio,
  38. uint32_t flags);
  39. #else
  40. /*
  41. * When a custom interrupt controller is specified, map the architecture
  42. * interrupt control functions to the SoC layer interrupt control functions.
  43. */
  44. void z_soc_irq_init(void);
  45. void z_soc_irq_enable(unsigned int irq);
  46. void z_soc_irq_disable(unsigned int irq);
  47. int z_soc_irq_is_enabled(unsigned int irq);
  48. void z_soc_irq_priority_set(
  49. unsigned int irq, unsigned int prio, unsigned int flags);
  50. unsigned int z_soc_irq_get_active(void);
  51. void z_soc_irq_eoi(unsigned int irq);
  52. #define arch_irq_enable(irq) z_soc_irq_enable(irq)
  53. #define arch_irq_disable(irq) z_soc_irq_disable(irq)
  54. #define arch_irq_is_enabled(irq) z_soc_irq_is_enabled(irq)
  55. #define z_arm_irq_priority_set(irq, prio, flags) \
  56. z_soc_irq_priority_set(irq, prio, flags)
  57. #endif /* !CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */
  58. extern void z_arm_int_exit(void);
  59. extern void z_arm_interrupt_init(void);
  60. /* macros convert value of it's argument to a string */
  61. #define DO_TOSTR(s) #s
  62. #define TOSTR(s) DO_TOSTR(s)
  63. /* concatenate the values of the arguments into one */
  64. #define DO_CONCAT(x, y) x ## y
  65. #define CONCAT(x, y) DO_CONCAT(x, y)
  66. /* Flags for use with IRQ_CONNECT() */
  67. /**
  68. * Set this interrupt up as a zero-latency IRQ. It has a fixed hardware
  69. * priority level (discarding what was supplied in the interrupt's priority
  70. * argument), and will run even if irq_lock() is active. Be careful!
  71. */
  72. #define IRQ_ZERO_LATENCY BIT(0)
  73. #ifdef CONFIG_CPU_CORTEX_M
  74. #define _CHECK_PRIO(priority_p, flags_p) \
  75. BUILD_ASSERT((flags_p & IRQ_ZERO_LATENCY) || \
  76. priority_p <= IRQ_PRIO_LOWEST, \
  77. "Invalid interrupt priority. Values must not exceed IRQ_PRIO_LOWEST");
  78. #else
  79. #define _CHECK_PRIO(priority_p, flags_p)
  80. #endif
  81. /* All arguments must be computable by the compiler at build time.
  82. *
  83. * Z_ISR_DECLARE will populate the .intList section with the interrupt's
  84. * parameters, which will then be used by gen_irq_tables.py to create
  85. * the vector table and the software ISR table. This is all done at
  86. * build-time.
  87. *
  88. * We additionally set the priority in the interrupt controller at
  89. * runtime.
  90. */
  91. #define ARCH_IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p) \
  92. { \
  93. BUILD_ASSERT(IS_ENABLED(CONFIG_ZERO_LATENCY_IRQS) || !(flags_p & IRQ_ZERO_LATENCY), \
  94. "ZLI interrupt registered but feature is disabled"); \
  95. _CHECK_PRIO(priority_p, flags_p) \
  96. Z_ISR_DECLARE(irq_p, 0, isr_p, isr_param_p); \
  97. z_arm_irq_priority_set(irq_p, priority_p, flags_p); \
  98. }
  99. #define ARCH_IRQ_DIRECT_CONNECT(irq_p, priority_p, isr_p, flags_p) \
  100. { \
  101. BUILD_ASSERT(IS_ENABLED(CONFIG_ZERO_LATENCY_IRQS) || !(flags_p & IRQ_ZERO_LATENCY), \
  102. "ZLI interrupt registered but feature is disabled"); \
  103. _CHECK_PRIO(priority_p, flags_p) \
  104. Z_ISR_DECLARE(irq_p, ISR_FLAG_DIRECT, isr_p, NULL); \
  105. z_arm_irq_priority_set(irq_p, priority_p, flags_p); \
  106. }
  107. #ifdef CONFIG_PM
  108. extern void _arch_isr_direct_pm(void);
  109. #define ARCH_ISR_DIRECT_PM() _arch_isr_direct_pm()
  110. #else
  111. #define ARCH_ISR_DIRECT_PM() do { } while (false)
  112. #endif
  113. #define ARCH_ISR_DIRECT_HEADER() arch_isr_direct_header()
  114. #define ARCH_ISR_DIRECT_FOOTER(swap) arch_isr_direct_footer(swap)
  115. /* arch/arm/core/aarch32/exc_exit.S */
  116. extern void z_arm_int_exit(void);
  117. #ifdef CONFIG_TRACING_ISR
  118. extern void sys_trace_isr_enter(void);
  119. extern void sys_trace_isr_exit(void);
  120. #endif
  121. static inline void arch_isr_direct_header(void)
  122. {
  123. #ifdef CONFIG_TRACING_ISR
  124. sys_trace_isr_enter();
  125. #endif
  126. }
  127. static inline void arch_isr_direct_footer(int maybe_swap)
  128. {
  129. #ifdef CONFIG_TRACING_ISR
  130. sys_trace_isr_exit();
  131. #endif
  132. if (maybe_swap != 0) {
  133. z_arm_int_exit();
  134. }
  135. }
  136. #define ARCH_ISR_DIRECT_DECLARE(name) \
  137. static inline int name##_body(void); \
  138. __attribute__ ((interrupt ("IRQ"))) void name(void) \
  139. { \
  140. int check_reschedule; \
  141. ISR_DIRECT_HEADER(); \
  142. check_reschedule = name##_body(); \
  143. ISR_DIRECT_FOOTER(check_reschedule); \
  144. } \
  145. static inline int name##_body(void)
  146. #if defined(CONFIG_DYNAMIC_DIRECT_INTERRUPTS)
  147. extern void z_arm_irq_direct_dynamic_dispatch_reschedule(void);
  148. extern void z_arm_irq_direct_dynamic_dispatch_no_reschedule(void);
  149. /**
  150. * @brief Macro to register an ISR Dispatcher (with or without re-scheduling
  151. * request) for dynamic direct interrupts.
  152. *
  153. * This macro registers the ISR dispatcher function for dynamic direct
  154. * interrupts for a particular IRQ line, allowing the use of dynamic
  155. * direct ISRs in the kernel for that interrupt source.
  156. * The dispatcher function is invoked when the hardware
  157. * interrupt occurs and then triggers the (software) Interrupt Service Routine
  158. * (ISR) that is registered dynamically (i.e. at run-time) into the software
  159. * ISR table stored in SRAM. The ISR must be connected with
  160. * irq_connect_dynamic() and enabled via irq_enable() before the dynamic direct
  161. * interrupt can be serviced. This ISR dispatcher must be configured by the
  162. * user to trigger thread re-secheduling upon return, using the @param resch
  163. * parameter.
  164. *
  165. * These ISRs are designed for performance-critical interrupt handling and do
  166. * not go through all of the common interrupt handling code.
  167. *
  168. * With respect to their declaration, dynamic 'direct' interrupts are regular
  169. * Zephyr interrupts; their signature must match void isr(void* parameter), as,
  170. * unlike regular direct interrupts, they are not placed directly into the
  171. * ROM hardware vector table but instead they are installed in the software
  172. * ISR table.
  173. *
  174. * The major differences with regular Zephyr interrupts are the following:
  175. * - Similar to direct interrupts, the call into the OS to exit power
  176. * management idle state is optional. Normal interrupts always do this
  177. * before the ISR is run, but with dynamic direct ones when and if it runs
  178. * is controlled by the placement of
  179. * a ISR_DIRECT_PM() macro, or omitted entirely.
  180. * - Similar to direct interrupts, scheduling decisions are optional. Unlike
  181. * direct interrupts, the decisions must be made at build time.
  182. * They are controlled by @param resch to this macro.
  183. *
  184. * @param irq_p IRQ line number.
  185. * @param priority_p Interrupt priority.
  186. * @param flags_p Architecture-specific IRQ configuration flags.
  187. * @param resch Set flag to 'reschedule' to request thread
  188. * re-scheduling upon ISR function. Set flag
  189. * 'no_reschedule' to skip thread re-scheduling
  190. *
  191. * Note: the function is an ARM Cortex-M only API.
  192. *
  193. * @return Interrupt vector assigned to this interrupt.
  194. */
  195. #define ARM_IRQ_DIRECT_DYNAMIC_CONNECT(irq_p, priority_p, flags_p, resch) \
  196. IRQ_DIRECT_CONNECT(irq_p, priority_p, \
  197. CONCAT(z_arm_irq_direct_dynamic_dispatch_, resch), flags_p)
  198. #endif /* CONFIG_DYNAMIC_DIRECT_INTERRUPTS */
  199. /* Spurious interrupt handler. Throws an error if called */
  200. extern void z_irq_spurious(const void *unused);
  201. #ifdef CONFIG_GEN_SW_ISR_TABLE
  202. /* Architecture-specific common entry point for interrupts from the vector
  203. * table. Most likely implemented in assembly. Looks up the correct handler
  204. * and parameter from the _sw_isr_table and executes it.
  205. */
  206. extern void _isr_wrapper(void);
  207. #endif
  208. #if defined(CONFIG_ARM_SECURE_FIRMWARE)
  209. /* Architecture-specific definition for the target security
  210. * state of an NVIC IRQ line.
  211. */
  212. typedef enum {
  213. IRQ_TARGET_STATE_SECURE = 0,
  214. IRQ_TARGET_STATE_NON_SECURE
  215. } irq_target_state_t;
  216. #endif /* CONFIG_ARM_SECURE_FIRMWARE */
  217. #endif /* _ASMLANGUAGE */
  218. #ifdef __cplusplus
  219. }
  220. #endif
  221. #endif /* ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_IRQ_H_ */