LCOV - code coverage report
Current view: top level - zephyr - irq.h Hit Total Coverage
Test: new.info Lines: 14 14 100.0 %
Date: 2024-12-22 00:14:23

          Line data    Source code
       1           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           1 : #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
      65           1 : 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
      90           1 : 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           1 : #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           1 : #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           1 : #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           1 : #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           1 : #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 spinlocks 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           1 : #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 spinlocks 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           1 : #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           1 : #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           1 : #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           1 : #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_ */

Generated by: LCOV version 1.14