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 Return IRQ level
285 * This routine returns the interrupt level number of the provided interrupt.
286 *
287 * @param irq IRQ number in its zephyr format
288 *
289 * @return 1 if IRQ level 1, 2 if IRQ level 2, 3 if IRQ level 3
290 */
irq_get_level(unsigned int irq)291 static inline unsigned int irq_get_level(unsigned int irq)
292 {
293 const uint32_t mask2 = BIT_MASK(CONFIG_2ND_LEVEL_INTERRUPT_BITS) <<
294 CONFIG_1ST_LEVEL_INTERRUPT_BITS;
295 const uint32_t mask3 = BIT_MASK(CONFIG_3RD_LEVEL_INTERRUPT_BITS) <<
296 (CONFIG_1ST_LEVEL_INTERRUPT_BITS + CONFIG_2ND_LEVEL_INTERRUPT_BITS);
297
298 if (IS_ENABLED(CONFIG_3RD_LEVEL_INTERRUPTS) && (irq & mask3) != 0) {
299 return 3;
300 }
301
302 if (IS_ENABLED(CONFIG_2ND_LEVEL_INTERRUPTS) && (irq & mask2) != 0) {
303 return 2;
304 }
305
306 return 1;
307 }
308
309 #if defined(CONFIG_2ND_LEVEL_INTERRUPTS)
310 /**
311 * @brief Return the 2nd level interrupt number
312 *
313 * This routine returns the second level irq number of the zephyr irq
314 * number passed in
315 *
316 * @param irq IRQ number in its zephyr format
317 *
318 * @return 2nd level IRQ number
319 */
irq_from_level_2(unsigned int irq)320 static inline unsigned int irq_from_level_2(unsigned int irq)
321 {
322 #if defined(CONFIG_3RD_LEVEL_INTERRUPTS)
323 return ((irq >> CONFIG_1ST_LEVEL_INTERRUPT_BITS) &
324 BIT_MASK(CONFIG_2ND_LEVEL_INTERRUPT_BITS)) - 1;
325 #else
326 return (irq >> CONFIG_1ST_LEVEL_INTERRUPT_BITS) - 1;
327 #endif
328 }
329
330 /**
331 * @brief Converts irq from level 1 to level 2 format
332 *
333 *
334 * This routine converts the input into the level 2 irq number format
335 *
336 * @note Values >= 0xFF are invalid
337 *
338 * @param irq IRQ number in its zephyr format
339 *
340 * @return 2nd level IRQ number
341 */
irq_to_level_2(unsigned int irq)342 static inline unsigned int irq_to_level_2(unsigned int irq)
343 {
344 return (irq + 1) << CONFIG_1ST_LEVEL_INTERRUPT_BITS;
345 }
346
347 /**
348 * @brief Returns the parent IRQ of the level 2 raw IRQ number
349 *
350 *
351 * The parent of a 2nd level interrupt is in the 1st byte
352 *
353 * @param irq IRQ number in its zephyr format
354 *
355 * @return 2nd level IRQ parent
356 */
irq_parent_level_2(unsigned int irq)357 static inline unsigned int irq_parent_level_2(unsigned int irq)
358 {
359 return irq & BIT_MASK(CONFIG_1ST_LEVEL_INTERRUPT_BITS);
360 }
361 #endif
362
363 #ifdef CONFIG_3RD_LEVEL_INTERRUPTS
364 /**
365 * @brief Return the 3rd level interrupt number
366 *
367 *
368 * This routine returns the third level irq number of the zephyr irq
369 * number passed in
370 *
371 * @param irq IRQ number in its zephyr format
372 *
373 * @return 3rd level IRQ number
374 */
irq_from_level_3(unsigned int irq)375 static inline unsigned int irq_from_level_3(unsigned int irq)
376 {
377 return (irq >> (CONFIG_1ST_LEVEL_INTERRUPT_BITS + CONFIG_2ND_LEVEL_INTERRUPT_BITS)) - 1;
378 }
379
380 /**
381 * @brief Converts irq from level 1 to level 3 format
382 *
383 *
384 * This routine converts the input into the level 3 irq number format
385 *
386 * @note Values >= 0xFF are invalid
387 *
388 * @param irq IRQ number in its zephyr format
389 *
390 * @return 3rd level IRQ number
391 */
irq_to_level_3(unsigned int irq)392 static inline unsigned int irq_to_level_3(unsigned int irq)
393 {
394 return (irq + 1) << (CONFIG_1ST_LEVEL_INTERRUPT_BITS + CONFIG_2ND_LEVEL_INTERRUPT_BITS);
395 }
396
397 /**
398 * @brief Returns the parent IRQ of the level 3 raw IRQ number
399 *
400 *
401 * The parent of a 3rd level interrupt is in the 2nd byte
402 *
403 * @param irq IRQ number in its zephyr format
404 *
405 * @return 3rd level IRQ parent
406 */
irq_parent_level_3(unsigned int irq)407 static inline unsigned int irq_parent_level_3(unsigned int irq)
408 {
409 return (irq >> CONFIG_1ST_LEVEL_INTERRUPT_BITS) &
410 BIT_MASK(CONFIG_2ND_LEVEL_INTERRUPT_BITS);
411 }
412 #endif
413
414 /**
415 * @brief Enable an IRQ.
416 *
417 * This routine enables interrupts from source @a irq.
418 *
419 * @param irq IRQ line.
420 */
421 #define irq_enable(irq) arch_irq_enable(irq)
422
423 /**
424 * @brief Disable an IRQ.
425 *
426 * This routine disables interrupts from source @a irq.
427 *
428 * @param irq IRQ line.
429 */
430 #define irq_disable(irq) arch_irq_disable(irq)
431
432 /**
433 * @brief Get IRQ enable state.
434 *
435 * This routine indicates if interrupts from source @a irq are enabled.
436 *
437 * @param irq IRQ line.
438 *
439 * @return interrupt enable state, true or false
440 */
441 #define irq_is_enabled(irq) arch_irq_is_enabled(irq)
442
443 /**
444 * @}
445 */
446
447 #ifdef __cplusplus
448 }
449 #endif
450
451 #endif /* ASMLANGUAGE */
452 #endif /* ZEPHYR_INCLUDE_IRQ_H_ */
453