1 /*
2 * Copyright (c) 2015 Intel corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /**
8 * @file
9 * @brief Public interface for configuring interrupts
10 */
11 #ifndef ZEPHYR_INCLUDE_IRQ_H_
12 #define ZEPHYR_INCLUDE_IRQ_H_
13
14 /* Pull in the arch-specific implementations */
15 #include <zephyr/arch/cpu.h>
16
17 #ifndef _ASMLANGUAGE
18 #include <zephyr/toolchain.h>
19 #include <zephyr/types.h>
20
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
24
25 /**
26 * @defgroup isr_apis Interrupt Service Routine APIs
27 * @ingroup kernel_apis
28 * @{
29 */
30
31 /**
32 * @brief Initialize an interrupt handler.
33 *
34 * This routine initializes an interrupt handler for an IRQ. The IRQ must be
35 * subsequently enabled before the interrupt handler begins servicing
36 * interrupts.
37 *
38 * @warning
39 * Although this routine is invoked at run-time, all of its arguments must be
40 * computable by the compiler at build time.
41 *
42 * @param irq_p IRQ line number.
43 * @param priority_p Interrupt priority.
44 * @param isr_p Address of interrupt service routine.
45 * @param isr_param_p Parameter passed to interrupt service routine.
46 * @param flags_p Architecture-specific IRQ configuration flags..
47 */
48 #define IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p) \
49 ARCH_IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p)
50
51 /**
52 * Configure a dynamic interrupt.
53 *
54 * Use this instead of IRQ_CONNECT() if arguments cannot be known at build time.
55 *
56 * @param irq IRQ line number
57 * @param priority Interrupt priority
58 * @param routine Interrupt service routine
59 * @param parameter ISR parameter
60 * @param flags Arch-specific IRQ configuration flags
61 *
62 * @return The vector assigned to this interrupt
63 */
64 static inline int
irq_connect_dynamic(unsigned int irq,unsigned int priority,void (* routine)(const void * parameter),const void * parameter,uint32_t flags)65 irq_connect_dynamic(unsigned int irq, unsigned int priority,
66 void (*routine)(const void *parameter),
67 const void *parameter, uint32_t flags)
68 {
69 return arch_irq_connect_dynamic(irq, priority, routine, parameter,
70 flags);
71 }
72
73 /**
74 * Disconnect a dynamic interrupt.
75 *
76 * Use this in conjunction with shared interrupts to remove a routine/parameter
77 * pair from the list of clients using the same interrupt line. If the interrupt
78 * is not being shared then the associated _sw_isr_table entry will be replaced
79 * by (NULL, z_irq_spurious) (default entry).
80 *
81 * @param irq IRQ line number
82 * @param priority Interrupt priority
83 * @param routine Interrupt service routine
84 * @param parameter ISR parameter
85 * @param flags Arch-specific IRQ configuration flags
86 *
87 * @return 0 in case of success, negative value otherwise
88 */
89 static inline int
irq_disconnect_dynamic(unsigned int irq,unsigned int priority,void (* routine)(const void * parameter),const void * parameter,uint32_t flags)90 irq_disconnect_dynamic(unsigned int irq, unsigned int priority,
91 void (*routine)(const void *parameter),
92 const void *parameter, uint32_t flags)
93 {
94 return arch_irq_disconnect_dynamic(irq, priority, routine,
95 parameter, flags);
96 }
97
98 /**
99 * @brief Initialize a 'direct' interrupt handler.
100 *
101 * This routine initializes an interrupt handler for an IRQ. The IRQ must be
102 * subsequently enabled via irq_enable() before the interrupt handler begins
103 * servicing interrupts.
104 *
105 * These ISRs are designed for performance-critical interrupt handling and do
106 * not go through common interrupt handling code. They must be implemented in
107 * such a way that it is safe to put them directly in the vector table. For
108 * ISRs written in C, The ISR_DIRECT_DECLARE() macro will do this
109 * automatically. For ISRs written in assembly it is entirely up to the
110 * developer to ensure that the right steps are taken.
111 *
112 * This type of interrupt currently has a few limitations compared to normal
113 * Zephyr interrupts:
114 * - No parameters are passed to the ISR.
115 * - No stack switch is done, the ISR will run on the interrupted context's
116 * stack, unless the architecture automatically does the stack switch in HW.
117 * - Interrupt locking state is unchanged from how the HW sets it when the ISR
118 * runs. On arches that enter ISRs with interrupts locked, they will remain
119 * locked.
120 * - Scheduling decisions are now optional, controlled by the return value of
121 * ISRs implemented with the ISR_DIRECT_DECLARE() macro
122 * - The call into the OS to exit power management idle state is now optional.
123 * Normal interrupts always do this before the ISR is run, but when it runs
124 * is now controlled by the placement of a ISR_DIRECT_PM() macro, or omitted
125 * entirely.
126 *
127 * @warning
128 * Although this routine is invoked at run-time, all of its arguments must be
129 * computable by the compiler at build time.
130 *
131 * @param irq_p IRQ line number.
132 * @param priority_p Interrupt priority.
133 * @param isr_p Address of interrupt service routine.
134 * @param flags_p Architecture-specific IRQ configuration flags.
135 */
136 #define IRQ_DIRECT_CONNECT(irq_p, priority_p, isr_p, flags_p) \
137 ARCH_IRQ_DIRECT_CONNECT(irq_p, priority_p, isr_p, flags_p)
138
139 /**
140 * @brief Common tasks before executing the body of an ISR
141 *
142 * This macro must be at the beginning of all direct interrupts and performs
143 * minimal architecture-specific tasks before the ISR itself can run. It takes
144 * no arguments and has no return value.
145 */
146 #define ISR_DIRECT_HEADER() ARCH_ISR_DIRECT_HEADER()
147
148 /**
149 * @brief Common tasks before exiting the body of an ISR
150 *
151 * This macro must be at the end of all direct interrupts and performs
152 * minimal architecture-specific tasks like EOI. It has no return value.
153 *
154 * In a normal interrupt, a check is done at end of interrupt to invoke
155 * z_swap() logic if the current thread is preemptible and there is another
156 * thread ready to run in the kernel's ready queue cache. This is now optional
157 * and controlled by the check_reschedule argument. If unsure, set to nonzero.
158 * On systems that do stack switching and nested interrupt tracking in software,
159 * z_swap() should only be called if this was a non-nested interrupt.
160 *
161 * @param check_reschedule If nonzero, additionally invoke scheduling logic
162 */
163 #define ISR_DIRECT_FOOTER(check_reschedule) \
164 ARCH_ISR_DIRECT_FOOTER(check_reschedule)
165
166 /**
167 * @brief Perform power management idle exit logic
168 *
169 * This macro may optionally be invoked somewhere in between IRQ_DIRECT_HEADER()
170 * and IRQ_DIRECT_FOOTER() invocations. It performs tasks necessary to
171 * exit power management idle state. It takes no parameters and returns no
172 * arguments. It may be omitted, but be careful!
173 */
174 #define ISR_DIRECT_PM() ARCH_ISR_DIRECT_PM()
175
176 /**
177 * @brief Helper macro to declare a direct interrupt service routine.
178 *
179 * This will declare the function in a proper way and automatically include
180 * the ISR_DIRECT_FOOTER() and ISR_DIRECT_HEADER() macros. The function should
181 * return nonzero status if a scheduling decision should potentially be made.
182 * See ISR_DIRECT_FOOTER() for more details on the scheduling decision.
183 *
184 * For architectures that support 'regular' and 'fast' interrupt types, where
185 * these interrupt types require different assembly language handling of
186 * registers by the ISR, this will always generate code for the 'fast'
187 * interrupt type.
188 *
189 * Example usage:
190 *
191 * ISR_DIRECT_DECLARE(my_isr)
192 * {
193 * bool done = do_stuff();
194 * ISR_DIRECT_PM(); // done after do_stuff() due to latency concerns
195 * if (!done) {
196 * return 0; // don't bother checking if we have to z_swap()
197 * }
198 *
199 * k_sem_give(some_sem);
200 * return 1;
201 * }
202 *
203 * @param name symbol name of the ISR
204 */
205 #define ISR_DIRECT_DECLARE(name) ARCH_ISR_DIRECT_DECLARE(name)
206
207 /**
208 * @brief Lock interrupts.
209 * @def irq_lock()
210 *
211 * This routine disables all interrupts on the CPU. It returns an unsigned
212 * integer "lock-out key", which is an architecture-dependent indicator of
213 * whether interrupts were locked prior to the call. The lock-out key must be
214 * passed to irq_unlock() to re-enable interrupts.
215 *
216 * @note
217 * This routine must also serve as a memory barrier to ensure the uniprocessor
218 * implementation of `k_spinlock_t` is correct.
219 *
220 * This routine can be called recursively, as long as the caller keeps track
221 * of each lock-out key that is generated. Interrupts are re-enabled by
222 * passing each of the keys to irq_unlock() in the reverse order they were
223 * acquired. (That is, each call to irq_lock() must be balanced by
224 * a corresponding call to irq_unlock().)
225 *
226 * This routine can only be invoked from supervisor mode. Some architectures
227 * (for example, ARM) will fail silently if invoked from user mode instead
228 * of generating an exception.
229 *
230 * @note
231 * This routine can be called by ISRs or by threads. If it is called by a
232 * thread, the interrupt lock is thread-specific; this means that interrupts
233 * remain disabled only while the thread is running. If the thread performs an
234 * operation that allows another thread to run (for example, giving a semaphore
235 * or sleeping for N milliseconds), the interrupt lock no longer applies and
236 * interrupts may be re-enabled while other processing occurs. When the thread
237 * once again becomes the current thread, the kernel re-establishes its
238 * interrupt lock; this ensures the thread won't be interrupted until it has
239 * explicitly released the interrupt lock it established.
240 *
241 * @warning
242 * The lock-out key should never be used to manually re-enable interrupts
243 * or to inspect or manipulate the contents of the CPU's interrupt bits.
244 *
245 * @return An architecture-dependent lock-out key representing the
246 * "interrupt disable state" prior to the call.
247 */
248 #ifdef CONFIG_SMP
249 unsigned int z_smp_global_lock(void);
250 #define irq_lock() z_smp_global_lock()
251 #else
252 #define irq_lock() arch_irq_lock()
253 #endif
254
255 /**
256 * @brief Unlock interrupts.
257 * @def irq_unlock()
258 *
259 * This routine reverses the effect of a previous call to irq_lock() using
260 * the associated lock-out key. The caller must call the routine once for
261 * each time it called irq_lock(), supplying the keys in the reverse order
262 * they were acquired, before interrupts are enabled.
263 *
264 * @note
265 * This routine must also serve as a memory barrier to ensure the uniprocessor
266 * implementation of `k_spinlock_t` is correct.
267 *
268 * This routine can only be invoked from supervisor mode. Some architectures
269 * (for example, ARM) will fail silently if invoked from user mode instead
270 * of generating an exception.
271 *
272 * @note Can be called by ISRs.
273 *
274 * @param key Lock-out key generated by irq_lock().
275 */
276 #ifdef CONFIG_SMP
277 void z_smp_global_unlock(unsigned int key);
278 #define irq_unlock(key) z_smp_global_unlock(key)
279 #else
280 #define irq_unlock(key) arch_irq_unlock(key)
281 #endif
282
283 /**
284 * @brief Enable an IRQ.
285 *
286 * This routine enables interrupts from source @a irq.
287 *
288 * @param irq IRQ line.
289 */
290 #define irq_enable(irq) arch_irq_enable(irq)
291
292 /**
293 * @brief Disable an IRQ.
294 *
295 * This routine disables interrupts from source @a irq.
296 *
297 * @param irq IRQ line.
298 */
299 #define irq_disable(irq) arch_irq_disable(irq)
300
301 /**
302 * @brief Get IRQ enable state.
303 *
304 * This routine indicates if interrupts from source @a irq are enabled.
305 *
306 * @param irq IRQ line.
307 *
308 * @return interrupt enable state, true or false
309 */
310 #define irq_is_enabled(irq) arch_irq_is_enabled(irq)
311
312 /**
313 * @}
314 */
315
316 #ifdef __cplusplus
317 }
318 #endif
319
320 #endif /* ASMLANGUAGE */
321 #endif /* ZEPHYR_INCLUDE_IRQ_H_ */
322