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

          Line data    Source code
       1           1 : /*
       2             :  * Copyright (c) 2014, Wind River Systems, Inc.
       3             :  *
       4             :  * SPDX-License-Identifier: Apache-2.0
       5             :  */
       6             : 
       7             : /**
       8             :  * @file
       9             :  * @brief Software-managed ISR table
      10             :  *
      11             :  * Data types for a software-managed ISR table, with a parameter per-ISR.
      12             :  */
      13             : 
      14             : #ifndef ZEPHYR_INCLUDE_SW_ISR_TABLE_H_
      15             : #define ZEPHYR_INCLUDE_SW_ISR_TABLE_H_
      16             : 
      17             : #if !defined(_ASMLANGUAGE)
      18             : #include <zephyr/device.h>
      19             : #include <zephyr/sys/iterable_sections.h>
      20             : #include <zephyr/types.h>
      21             : #include <zephyr/toolchain.h>
      22             : #include <zephyr/sys/util.h>
      23             : 
      24             : #ifdef __cplusplus
      25             : extern "C" {
      26             : #endif
      27             : 
      28             : /* Default vector for the IRQ vector table */
      29             : void _isr_wrapper(void);
      30             : 
      31             : /* Spurious interrupt handler. Throws an error if called */
      32             : void z_irq_spurious(const void *unused);
      33             : 
      34             : /*
      35             :  * Note the order: arg first, then ISR. This allows a table entry to be
      36             :  * loaded arg -> r0, isr -> r3 in _isr_wrapper with one ldmia instruction,
      37             :  * on ARM Cortex-M (Thumb2).
      38             :  */
      39             : struct _isr_table_entry {
      40             :         const void *arg;
      41             :         void (*isr)(const void *);
      42             : };
      43             : 
      44             : /* The software ISR table itself, an array of these structures indexed by the
      45             :  * irq line
      46             :  */
      47             : extern struct _isr_table_entry _sw_isr_table[];
      48             : 
      49             : struct _irq_parent_entry {
      50             :         const struct device *dev;
      51             :         unsigned int level;
      52             :         unsigned int irq;
      53             :         unsigned int offset;
      54             : };
      55             : 
      56             : /**
      57             :  * @cond INTERNAL_HIDDEN
      58             :  */
      59             : 
      60             : /* Mapping between aggregator level to order */
      61             : #define Z_STR_L2 2ND
      62             : #define Z_STR_L3 3RD
      63             : /**
      64             :  * @brief Get the Software ISR table offset Kconfig for the given aggregator level
      65             :  *
      66             :  * @param l Aggregator level, must be 2 or 3
      67             :  *
      68             :  * @return `CONFIG_2ND_LVL_ISR_TBL_OFFSET` if second level aggregator,
      69             :  * `CONFIG_3RD_LVL_ISR_TBL_OFFSET` if third level aggregator
      70             :  */
      71             : #define Z_SW_ISR_TBL_KCONFIG_BY_ALVL(l) CONCAT(CONFIG_, CONCAT(Z_STR_L, l), _LVL_ISR_TBL_OFFSET)
      72             : 
      73             : /**
      74             :  * INTERNAL_HIDDEN @endcond
      75             :  */
      76             : 
      77             : /**
      78             :  * @brief Get an interrupt controller node's level base ISR table offset.
      79             :  *
      80             :  * @param node_id node identifier of the interrupt controller
      81             :  *
      82             :  * @return `CONFIG_2ND_LVL_ISR_TBL_OFFSET` if node_id is a second level aggregator,
      83             :  * `CONFIG_3RD_LVL_ISR_TBL_OFFSET` if it is a third level aggregator
      84             :  */
      85           1 : #define INTC_BASE_ISR_TBL_OFFSET(node_id)                                                          \
      86             :         Z_SW_ISR_TBL_KCONFIG_BY_ALVL(DT_INTC_GET_AGGREGATOR_LEVEL(node_id))
      87             : 
      88             : /**
      89             :  * @brief Get the SW ISR table offset for an instance of interrupt controller
      90             :  *
      91             :  * @param inst DT_DRV_COMPAT interrupt controller driver instance number
      92             :  *
      93             :  * @return Software ISR table offset of the interrupt controller
      94             :  */
      95           1 : #define INTC_INST_ISR_TBL_OFFSET(inst)                                                             \
      96             :         (INTC_BASE_ISR_TBL_OFFSET(DT_DRV_INST(inst)) + (inst * CONFIG_MAX_IRQ_PER_AGGREGATOR))
      97             : 
      98             : /**
      99             :  * @brief Get the SW ISR table offset for a child interrupt controller
     100             :  *
     101             :  * @details This macro is a alternative form of the `INTC_INST_ISR_TBL_OFFSET`. This is used by
     102             :  * pseudo interrupt controller devices that are child of a main interrupt controller device.
     103             :  *
     104             :  * @param node_id node identifier of the child interrupt controller
     105             :  *
     106             :  * @return Software ISR table offset of the child
     107             :  */
     108           1 : #define INTC_CHILD_ISR_TBL_OFFSET(node_id)                                                         \
     109             :         (INTC_BASE_ISR_TBL_OFFSET(node_id) +                                                       \
     110             :          (DT_NODE_CHILD_IDX(node_id) * CONFIG_MAX_IRQ_PER_AGGREGATOR))
     111             : 
     112             : /**
     113             :  * @brief Register an  interrupt controller with the software ISR table
     114             :  *
     115             :  * @param _name Name of the interrupt controller (must be unique)
     116             :  * @param _dev Pointer to the interrupt controller device instance
     117             :  * @param _irq Interrupt controller IRQ number
     118             :  * @param _offset Software ISR table offset of the interrupt controller
     119             :  * @param _level Interrupt controller aggregator level
     120             :  */
     121           1 : #define IRQ_PARENT_ENTRY_DEFINE(_name, _dev, _irq, _offset, _level)                                \
     122             :         static const STRUCT_SECTION_ITERABLE_ALTERNATE(intc_table, _irq_parent_entry, _name) = {   \
     123             :                 .dev = _dev,                                                                       \
     124             :                 .level = _level,                                                                   \
     125             :                 .irq = _irq,                                                                       \
     126             :                 .offset = _offset,                                                                 \
     127             :         }
     128             : 
     129             : /*
     130             :  * Data structure created in a special binary .intlist section for each
     131             :  * configured interrupt. gen_irq_tables.py pulls this out of the binary and
     132             :  * uses it to create the IRQ vector table and the _sw_isr_table.
     133             :  *
     134             :  * More discussion in include/linker/intlist.ld
     135             :  *
     136             :  * This is a version used when CONFIG_ISR_TABLES_LOCAL_DECLARATION is disabled.
     137             :  * See _isr_list_sname used otherwise.
     138             :  */
     139             : struct _isr_list {
     140             :         /** IRQ line number */
     141             :         int32_t irq;
     142             :         /** Flags for this IRQ, see ISR_FLAG_* definitions */
     143             :         int32_t flags;
     144             :         /** ISR to call */
     145             :         void *func;
     146             :         /** Parameter for non-direct IRQs */
     147             :         const void *param;
     148             : };
     149             : 
     150             : /*
     151             :  * Data structure created in a special binary .intlist section for each
     152             :  * configured interrupt. gen_isr_tables.py pulls this out of the binary and
     153             :  * uses it to create linker script chunks that would place interrupt table entries
     154             :  * in the right place in the memory.
     155             :  *
     156             :  * This is a version used when CONFIG_ISR_TABLES_LOCAL_DECLARATION is enabled.
     157             :  * See _isr_list used otherwise.
     158             :  */
     159             : struct _isr_list_sname {
     160             :         /** IRQ line number */
     161             :         int32_t irq;
     162             :         /** Flags for this IRQ, see ISR_FLAG_* definitions */
     163             :         int32_t flags;
     164             :         /** The section name */
     165             :         const char sname[];
     166             : };
     167             : 
     168             : #ifdef CONFIG_SHARED_INTERRUPTS
     169             : struct z_shared_isr_table_entry {
     170             :         struct _isr_table_entry clients[CONFIG_SHARED_IRQ_MAX_NUM_CLIENTS];
     171             :         size_t client_num;
     172             : };
     173             : 
     174             : void z_shared_isr(const void *data);
     175             : 
     176             : extern struct z_shared_isr_table_entry z_shared_sw_isr_table[];
     177             : #endif /* CONFIG_SHARED_INTERRUPTS */
     178             : 
     179             : /** This interrupt gets put directly in the vector table */
     180           1 : #define ISR_FLAG_DIRECT BIT(0)
     181             : 
     182             : #define _MK_ISR_NAME(x, y) __MK_ISR_NAME(x, y)
     183             : #define __MK_ISR_NAME(x, y) __isr_ ## x ## _irq_ ## y
     184             : 
     185             : 
     186             : #if defined(CONFIG_ISR_TABLES_LOCAL_DECLARATION)
     187             : 
     188             : #define _MK_ISR_ELEMENT_NAME(func, id) __MK_ISR_ELEMENT_NAME(func, id)
     189             : #define __MK_ISR_ELEMENT_NAME(func, id) __isr_table_entry_ ## func ## _irq_ ## id
     190             : 
     191             : #define _MK_IRQ_ELEMENT_NAME(func, id) __MK_ISR_ELEMENT_NAME(func, id)
     192             : #define __MK_IRQ_ELEMENT_NAME(func, id) __irq_table_entry_ ## func ## _irq_ ## id
     193             : 
     194             : #define _MK_ISR_SECTION_NAME(prefix, file, counter) \
     195             :         "." Z_STRINGIFY(prefix)"."file"." Z_STRINGIFY(counter)
     196             : 
     197             : #define _MK_ISR_ELEMENT_SECTION(counter) _MK_ISR_SECTION_NAME(irq, __FILE__, counter)
     198             : #define _MK_IRQ_ELEMENT_SECTION(counter) _MK_ISR_SECTION_NAME(isr, __FILE__, counter)
     199             : 
     200             : /* Separated macro to create ISR table entry only.
     201             :  * Used by Z_ISR_DECLARE and ISR tables generation script.
     202             :  */
     203             : #define _Z_ISR_TABLE_ENTRY(irq, func, param, sect) \
     204             :         static Z_DECL_ALIGN(struct _isr_table_entry)                                      \
     205             :                 __attribute__((section(sect)))                                            \
     206             :                 __used _MK_ISR_ELEMENT_NAME(func, __COUNTER__) = {                        \
     207             :                         .arg = (const void *)(param),                                     \
     208             :                         .isr = (void (*)(const void *))(void *)(func)                     \
     209             :         }
     210             : 
     211             : #define Z_ISR_DECLARE_C(irq, flags, func, param, counter) \
     212             :         _Z_ISR_DECLARE_C(irq, flags, func, param, counter)
     213             : 
     214             : #define _Z_ISR_DECLARE_C(irq, flags, func, param, counter)                                \
     215             :         _Z_ISR_TABLE_ENTRY(irq, func, param, _MK_ISR_ELEMENT_SECTION(counter));           \
     216             :         static struct _isr_list_sname Z_GENERIC_SECTION(.intList)                         \
     217             :                 __used _MK_ISR_NAME(func, counter) =                                      \
     218             :                 {irq, flags, _MK_ISR_ELEMENT_SECTION(counter)}
     219             : 
     220             : /* Create an entry for _isr_table to be then placed by the linker.
     221             :  * An instance of struct _isr_list which gets put in the .intList
     222             :  * section is created with the name of the section where _isr_table entry is placed to be then
     223             :  * used by isr generation script to create linker script chunk.
     224             :  */
     225             : #define Z_ISR_DECLARE(irq, flags, func, param)                                            \
     226             :         BUILD_ASSERT(((flags) & ISR_FLAG_DIRECT) == 0, "Use Z_ISR_DECLARE_DIRECT macro"); \
     227             :         Z_ISR_DECLARE_C(irq, flags, func, param, __COUNTER__)
     228             : 
     229             : 
     230             : /* Separated macro to create ISR Direct table entry only.
     231             :  * Used by Z_ISR_DECLARE_DIRECT and ISR tables generation script.
     232             :  */
     233             : #define _Z_ISR_DIRECT_TABLE_ENTRY(irq, func, sect)                                                 \
     234             :         COND_CODE_1(CONFIG_IRQ_VECTOR_TABLE_JUMP_BY_ADDRESS, (                                     \
     235             :                         static Z_DECL_ALIGN(uintptr_t)                                             \
     236             :                         __attribute__((section(sect)))                                             \
     237             :                         __used _MK_IRQ_ELEMENT_NAME(func, __COUNTER__) = ((uintptr_t)(func));      \
     238             :                 ), (                                                                               \
     239             :                         static void __attribute__((section(sect))) __attribute__((naked))          \
     240             :                         __used _MK_IRQ_ELEMENT_NAME(func, __COUNTER__)(void) {                     \
     241             :                                 __asm(ARCH_IRQ_VECTOR_JUMP_CODE(func));                            \
     242             :                         }                                                                          \
     243             :                 ))
     244             : 
     245             : #define Z_ISR_DECLARE_DIRECT_C(irq, flags, func, counter) \
     246             :         _Z_ISR_DECLARE_DIRECT_C(irq, flags, func, counter)
     247             : 
     248             : #define _Z_ISR_DECLARE_DIRECT_C(irq, flags, func, counter)                                         \
     249             :         _Z_ISR_DIRECT_TABLE_ENTRY(irq, func, _MK_IRQ_ELEMENT_SECTION(counter));                    \
     250             :         static struct _isr_list_sname Z_GENERIC_SECTION(.intList)                                  \
     251             :                 __used _MK_ISR_NAME(func, counter) = {                                             \
     252             :                         irq,                                                                       \
     253             :                         ISR_FLAG_DIRECT | (flags),                                                 \
     254             :                         _MK_IRQ_ELEMENT_SECTION(counter)}
     255             : 
     256             : /* Create an entry to irq table and place it in specific section which name is then placed
     257             :  * in an instance of struct _isr_list to be then used by the isr generation script to create
     258             :  * the linker script chunks.
     259             :  */
     260             : #define Z_ISR_DECLARE_DIRECT(irq, flags, func)                                                     \
     261             :         BUILD_ASSERT(IS_ENABLED(CONFIG_IRQ_VECTOR_TABLE_JUMP_BY_ADDRESS) ||                        \
     262             :                 IS_ENABLED(CONFIG_IRQ_VECTOR_TABLE_JUMP_BY_CODE),                                  \
     263             :                 "CONFIG_IRQ_VECTOR_TABLE_JUMP_BY_{ADDRESS,CODE} not set");                         \
     264             :         Z_ISR_DECLARE_DIRECT_C(irq, flags, func, __COUNTER__)
     265             : 
     266             : 
     267             : #else /* defined(CONFIG_ISR_TABLES_LOCAL_DECLARATION) */
     268             : 
     269             : /* Create an instance of struct _isr_list which gets put in the .intList
     270             :  * section. This gets consumed by gen_isr_tables.py which creates the vector
     271             :  * and/or SW ISR tables.
     272             :  */
     273             : #define Z_ISR_DECLARE(irq, flags, func, param) \
     274             :         static Z_DECL_ALIGN(struct _isr_list) Z_GENERIC_SECTION(.intList) \
     275             :                 __used _MK_ISR_NAME(func, __COUNTER__) = \
     276             :                         {irq, flags, (void *)&func, (const void *)param}
     277             : 
     278             : /* The version of the Z_ISR_DECLARE that should be used for direct ISR declaration.
     279             :  * It is here for the API match the version with CONFIG_ISR_TABLES_LOCAL_DECLARATION enabled.
     280             :  */
     281             : #define Z_ISR_DECLARE_DIRECT(irq, flags, func) \
     282             :         Z_ISR_DECLARE(irq, ISR_FLAG_DIRECT | (flags), func, NULL)
     283             : 
     284             : #endif
     285             : 
     286           0 : #define IRQ_TABLE_SIZE (CONFIG_NUM_IRQS - CONFIG_GEN_IRQ_START_VECTOR)
     287             : 
     288             : #ifdef CONFIG_DYNAMIC_INTERRUPTS
     289             : void z_isr_install(unsigned int irq, void (*routine)(const void *),
     290             :                    const void *param);
     291             : 
     292             : #ifdef CONFIG_SHARED_INTERRUPTS
     293             : int z_isr_uninstall(unsigned int irq, void (*routine)(const void *),
     294             :                     const void *param);
     295             : #endif /* CONFIG_SHARED_INTERRUPTS */
     296             : #endif
     297             : 
     298             : #ifdef __cplusplus
     299             : }
     300             : #endif
     301             : 
     302             : #endif /* _ASMLANGUAGE */
     303             : 
     304             : #endif /* ZEPHYR_INCLUDE_SW_ISR_TABLE_H_ */

Generated by: LCOV version 1.14