LCOV - code coverage report
Current view: top level - zephyr - sw_isr_table.h Coverage Total Hit
Test: new.info Lines: 85.7 % 7 6
Test Date: 2025-09-05 16:43:28

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

Generated by: LCOV version 2.0-1