LCOV - code coverage report
Current view: top level - zephyr/arch/arm - irq.h Hit Total Coverage
Test: new.info Lines: 2 15 13.3 %
Date: 2024-12-21 18:13:37

          Line data    Source code
       1           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             : /**
       9             :  * @file
      10             :  * @brief ARM AArch32 public interrupt handling
      11             :  *
      12             :  * ARM AArch32-specific kernel interrupt handling interface. Included by
      13             :  * arm/arch.h.
      14             :  */
      15             : 
      16             : #ifndef ZEPHYR_INCLUDE_ARCH_ARM_IRQ_H_
      17             : #define ZEPHYR_INCLUDE_ARCH_ARM_IRQ_H_
      18             : 
      19             : #include <zephyr/sw_isr_table.h>
      20             : #include <stdbool.h>
      21             : 
      22             : #ifdef __cplusplus
      23             : extern "C" {
      24             : #endif
      25             : 
      26             : #ifdef _ASMLANGUAGE
      27             : GTEXT(z_arm_int_exit);
      28             : GTEXT(arch_irq_enable)
      29             : GTEXT(arch_irq_disable)
      30             : GTEXT(arch_irq_is_enabled)
      31             : #if defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER)
      32             : GTEXT(z_soc_irq_get_active)
      33             : GTEXT(z_soc_irq_eoi)
      34             : #endif /* CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */
      35             : #else
      36             : 
      37             : #if !defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER)
      38             : 
      39           0 : extern void arch_irq_enable(unsigned int irq);
      40           0 : extern void arch_irq_disable(unsigned int irq);
      41           0 : extern int arch_irq_is_enabled(unsigned int irq);
      42             : 
      43             : /* internal routine documented in C file, needed by IRQ_CONNECT() macro */
      44             : extern void z_arm_irq_priority_set(unsigned int irq, unsigned int prio,
      45             :                                    uint32_t flags);
      46             : 
      47             : #else
      48             : 
      49             : /*
      50             :  * When a custom interrupt controller is specified, map the architecture
      51             :  * interrupt control functions to the SoC layer interrupt control functions.
      52             :  */
      53             : 
      54             : void z_soc_irq_init(void);
      55             : void z_soc_irq_enable(unsigned int irq);
      56             : void z_soc_irq_disable(unsigned int irq);
      57             : int z_soc_irq_is_enabled(unsigned int irq);
      58             : 
      59             : void z_soc_irq_priority_set(
      60             :         unsigned int irq, unsigned int prio, unsigned int flags);
      61             : 
      62             : unsigned int z_soc_irq_get_active(void);
      63             : void z_soc_irq_eoi(unsigned int irq);
      64             : 
      65             : #define arch_irq_enable(irq)            z_soc_irq_enable(irq)
      66             : #define arch_irq_disable(irq)           z_soc_irq_disable(irq)
      67             : #define arch_irq_is_enabled(irq)        z_soc_irq_is_enabled(irq)
      68             : 
      69             : #define z_arm_irq_priority_set(irq, prio, flags)        \
      70             :         z_soc_irq_priority_set(irq, prio, flags)
      71             : 
      72             : #endif /* !CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */
      73             : 
      74             : extern void z_arm_int_exit(void);
      75             : 
      76             : extern void z_arm_interrupt_init(void);
      77             : 
      78             : /* Flags for use with IRQ_CONNECT() */
      79             : /**
      80             :  * Set this interrupt up as a zero-latency IRQ. If CONFIG_ZERO_LATENCY_LEVELS
      81             :  * is 1 it has a fixed hardware priority level (discarding what was supplied
      82             :  * in the interrupt's priority argument). If CONFIG_ZERO_LATENCY_LEVELS is
      83             :  * greater 1 it has the priority level assigned by the argument.
      84             :  * The interrupt will run even if irq_lock() is active. Be careful!
      85             :  */
      86           1 : #define IRQ_ZERO_LATENCY        BIT(0)
      87             : 
      88             : #ifdef CONFIG_CPU_CORTEX_M
      89             : 
      90             : #if defined(CONFIG_ZERO_LATENCY_LEVELS)
      91             : #define ZERO_LATENCY_LEVELS CONFIG_ZERO_LATENCY_LEVELS
      92             : #else
      93             : #define ZERO_LATENCY_LEVELS 1
      94             : #endif
      95             : 
      96             : #define _CHECK_PRIO(priority_p, flags_p) \
      97             :         BUILD_ASSERT(((flags_p & IRQ_ZERO_LATENCY) && \
      98             :                       ((ZERO_LATENCY_LEVELS == 1) || \
      99             :                        (priority_p < ZERO_LATENCY_LEVELS))) || \
     100             :                      (priority_p <= IRQ_PRIO_LOWEST), \
     101             :                      "Invalid interrupt priority. Values must not exceed IRQ_PRIO_LOWEST");
     102             : #else
     103             : #define _CHECK_PRIO(priority_p, flags_p)
     104             : #endif
     105             : 
     106             : /* All arguments must be computable by the compiler at build time.
     107             :  *
     108             :  * Z_ISR_DECLARE will populate the .intList section with the interrupt's
     109             :  * parameters, which will then be used by gen_irq_tables.py to create
     110             :  * the vector table and the software ISR table. This is all done at
     111             :  * build-time.
     112             :  *
     113             :  * We additionally set the priority in the interrupt controller at
     114             :  * runtime.
     115             :  */
     116           0 : #define ARCH_IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p) \
     117             : { \
     118             :         BUILD_ASSERT(IS_ENABLED(CONFIG_ZERO_LATENCY_IRQS) || !(flags_p & IRQ_ZERO_LATENCY), \
     119             :                         "ZLI interrupt registered but feature is disabled"); \
     120             :         _CHECK_PRIO(priority_p, flags_p) \
     121             :         Z_ISR_DECLARE(irq_p, 0, isr_p, isr_param_p); \
     122             :         z_arm_irq_priority_set(irq_p, priority_p, flags_p); \
     123             : }
     124             : 
     125           0 : #define ARCH_IRQ_DIRECT_CONNECT(irq_p, priority_p, isr_p, flags_p) \
     126             : { \
     127             :         BUILD_ASSERT(IS_ENABLED(CONFIG_ZERO_LATENCY_IRQS) || !(flags_p & IRQ_ZERO_LATENCY), \
     128             :                         "ZLI interrupt registered but feature is disabled"); \
     129             :         _CHECK_PRIO(priority_p, flags_p) \
     130             :         Z_ISR_DECLARE_DIRECT(irq_p, ISR_FLAG_DIRECT, isr_p); \
     131             :         z_arm_irq_priority_set(irq_p, priority_p, flags_p); \
     132             : }
     133             : 
     134             : #ifdef CONFIG_PM
     135             : extern void _arch_isr_direct_pm(void);
     136             : #define ARCH_ISR_DIRECT_PM() _arch_isr_direct_pm()
     137             : #else
     138           0 : #define ARCH_ISR_DIRECT_PM() do { } while (false)
     139             : #endif
     140             : 
     141           0 : #define ARCH_ISR_DIRECT_HEADER() arch_isr_direct_header()
     142           0 : #define ARCH_ISR_DIRECT_FOOTER(swap) arch_isr_direct_footer(swap)
     143             : 
     144             : /* arch/arm/core/exc_exit.S */
     145             : extern void z_arm_int_exit(void);
     146             : 
     147             : #ifdef CONFIG_TRACING_ISR
     148             : extern void sys_trace_isr_enter(void);
     149             : extern void sys_trace_isr_exit(void);
     150             : #endif
     151             : 
     152           0 : static inline void arch_isr_direct_header(void)
     153             : {
     154             : #ifdef CONFIG_TRACING_ISR
     155             :         sys_trace_isr_enter();
     156             : #endif
     157             : }
     158             : 
     159           0 : static inline void arch_isr_direct_footer(int maybe_swap)
     160             : {
     161             : #ifdef CONFIG_TRACING_ISR
     162             :         sys_trace_isr_exit();
     163             : #endif
     164             :         if (maybe_swap != 0) {
     165             :                 z_arm_int_exit();
     166             :         }
     167             : }
     168             : 
     169             : #if defined(__clang__)
     170             : #define ARCH_ISR_DIAG_OFF \
     171             :         _Pragma("clang diagnostic push") \
     172             :         _Pragma("clang diagnostic ignored \"-Wextra\"")
     173             : #define ARCH_ISR_DIAG_ON _Pragma("clang diagnostic pop")
     174             : #elif defined(__GNUC__)
     175             : #define ARCH_ISR_DIAG_OFF \
     176             :         _Pragma("GCC diagnostic push") \
     177             :         _Pragma("GCC diagnostic ignored \"-Wattributes\"")
     178             : #define ARCH_ISR_DIAG_ON _Pragma("GCC diagnostic pop")
     179             : #else
     180           0 : #define ARCH_ISR_DIAG_OFF
     181           0 : #define ARCH_ISR_DIAG_ON
     182             : #endif
     183             : 
     184           0 : #define ARCH_ISR_DIRECT_DECLARE(name) \
     185             :         static inline int name##_body(void); \
     186             :         ARCH_ISR_DIAG_OFF \
     187             :         __attribute__ ((interrupt ("IRQ"))) void name(void) \
     188             :         { \
     189             :                 int check_reschedule; \
     190             :                 ISR_DIRECT_HEADER(); \
     191             :                 check_reschedule = name##_body(); \
     192             :                 ISR_DIRECT_FOOTER(check_reschedule); \
     193             :         } \
     194             :         ARCH_ISR_DIAG_ON \
     195             :         static inline int name##_body(void)
     196             : 
     197             : #if defined(CONFIG_DYNAMIC_DIRECT_INTERRUPTS)
     198             : 
     199             : extern void z_arm_irq_direct_dynamic_dispatch_reschedule(void);
     200             : extern void z_arm_irq_direct_dynamic_dispatch_no_reschedule(void);
     201             : 
     202             : /**
     203             :  * @brief Macro to register an ISR Dispatcher (with or without re-scheduling
     204             :  * request) for dynamic direct interrupts.
     205             :  *
     206             :  * This macro registers the ISR dispatcher function for dynamic direct
     207             :  * interrupts for a particular IRQ line, allowing the use of dynamic
     208             :  * direct ISRs in the kernel for that interrupt source.
     209             :  * The dispatcher function is invoked when the hardware
     210             :  * interrupt occurs and then triggers the (software) Interrupt Service Routine
     211             :  * (ISR) that is registered dynamically (i.e. at run-time) into the software
     212             :  * ISR table stored in SRAM. The ISR must be connected with
     213             :  * irq_connect_dynamic() and enabled via irq_enable() before the dynamic direct
     214             :  * interrupt can be serviced. This ISR dispatcher must be configured by the
     215             :  * user to trigger thread re-secheduling upon return, using the @param resch
     216             :  * parameter.
     217             :  *
     218             :  * These ISRs are designed for performance-critical interrupt handling and do
     219             :  * not go through all of the common interrupt handling code.
     220             :  *
     221             :  * With respect to their declaration, dynamic 'direct' interrupts are regular
     222             :  * Zephyr interrupts; their signature must match void isr(void* parameter), as,
     223             :  * unlike regular direct interrupts, they are not placed directly into the
     224             :  * ROM hardware vector table but instead they are installed in the software
     225             :  * ISR table.
     226             :  *
     227             :  * The major differences with regular Zephyr interrupts are the following:
     228             :  * - Similar to direct interrupts, the call into the OS to exit power
     229             :  *   management idle state is optional. Normal interrupts always do this
     230             :  *   before the ISR is run, but with dynamic direct ones when and if it runs
     231             :  *   is controlled by the placement of
     232             :  *   a ISR_DIRECT_PM() macro, or omitted entirely.
     233             :  * - Similar to direct interrupts, scheduling decisions are optional. Unlike
     234             :  *   direct interrupts, the decisions must be made at build time.
     235             :  *   They are controlled by @param resch to this macro.
     236             :  *
     237             :  * @param irq_p IRQ line number.
     238             :  * @param priority_p Interrupt priority.
     239             :  * @param flags_p Architecture-specific IRQ configuration flags.
     240             :  * @param resch Set flag to 'reschedule' to request thread
     241             :  *              re-scheduling upon ISR function. Set flag
     242             :  *              'no_reschedule' to skip thread re-scheduling
     243             :  *
     244             :  * Note: the function is an ARM Cortex-M only API.
     245             :  *
     246             :  * @return Interrupt vector assigned to this interrupt.
     247             :  */
     248             : #define ARM_IRQ_DIRECT_DYNAMIC_CONNECT(irq_p, priority_p, flags_p, resch) \
     249             :         IRQ_DIRECT_CONNECT(irq_p, priority_p, \
     250             :                 _CONCAT(z_arm_irq_direct_dynamic_dispatch_, resch), flags_p)
     251             : 
     252             : #endif /* CONFIG_DYNAMIC_DIRECT_INTERRUPTS */
     253             : 
     254             : #if defined(CONFIG_ARM_SECURE_FIRMWARE)
     255             : /* Architecture-specific definition for the target security
     256             :  * state of an NVIC IRQ line.
     257             :  */
     258             : typedef enum {
     259             :         IRQ_TARGET_STATE_SECURE = 0,
     260             :         IRQ_TARGET_STATE_NON_SECURE
     261             : } irq_target_state_t;
     262             : 
     263             : #endif /* CONFIG_ARM_SECURE_FIRMWARE */
     264             : 
     265             : #endif /* _ASMLANGUAGE */
     266             : 
     267             : #ifdef __cplusplus
     268             : }
     269             : #endif
     270             : 
     271             : #endif /* ZEPHYR_INCLUDE_ARCH_ARM_IRQ_H_ */

Generated by: LCOV version 1.14