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/types.h>
19 #include <zephyr/toolchain.h>
20 
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
24 
25 /* Default vector for the IRQ vector table */
26 extern void _isr_wrapper(void);
27 
28 /* Spurious interrupt handler. Throws an error if called */
29 extern void z_irq_spurious(const void *unused);
30 
31 /*
32  * Note the order: arg first, then ISR. This allows a table entry to be
33  * loaded arg -> r0, isr -> r3 in _isr_wrapper with one ldmia instruction,
34  * on ARM Cortex-M (Thumb2).
35  */
36 struct _isr_table_entry {
37 	const void *arg;
38 	void (*isr)(const void *);
39 };
40 
41 /* The software ISR table itself, an array of these structures indexed by the
42  * irq line
43  */
44 extern struct _isr_table_entry _sw_isr_table[];
45 
46 /*
47  * Data structure created in a special binary .intlist section for each
48  * configured interrupt. gen_irq_tables.py pulls this out of the binary and
49  * uses it to create the IRQ vector table and the _sw_isr_table.
50  *
51  * More discussion in include/linker/intlist.ld
52  */
53 struct _isr_list {
54 	/** IRQ line number */
55 	int32_t irq;
56 	/** Flags for this IRQ, see ISR_FLAG_* definitions */
57 	int32_t flags;
58 	/** ISR to call */
59 	void *func;
60 	/** Parameter for non-direct IRQs */
61 	const void *param;
62 };
63 
64 #ifdef CONFIG_SHARED_INTERRUPTS
65 struct z_shared_isr_client {
66 	void (*isr)(const void *arg);
67 	const void *arg;
68 };
69 
70 struct z_shared_isr_table_entry {
71 	struct z_shared_isr_client clients[CONFIG_SHARED_IRQ_MAX_NUM_CLIENTS];
72 	size_t client_num;
73 };
74 
75 void z_shared_isr(const void *data);
76 
77 extern struct z_shared_isr_table_entry z_shared_sw_isr_table[];
78 #endif /* CONFIG_SHARED_INTERRUPTS */
79 
80 /**
81  * @brief Helper function used to compute the index in _sw_isr_table
82  * based on passed IRQ.
83  *
84  * @param irq IRQ number in its zephyr format
85  *
86  * @return corresponding index in _sw_isr_table
87  */
88 unsigned int z_get_sw_isr_table_idx(unsigned int irq);
89 
90 /** This interrupt gets put directly in the vector table */
91 #define ISR_FLAG_DIRECT BIT(0)
92 
93 #define _MK_ISR_NAME(x, y) __MK_ISR_NAME(x, y)
94 #define __MK_ISR_NAME(x, y) __isr_ ## x ## _irq_ ## y
95 
96 /* Create an instance of struct _isr_list which gets put in the .intList
97  * section. This gets consumed by gen_isr_tables.py which creates the vector
98  * and/or SW ISR tables.
99  */
100 #define Z_ISR_DECLARE(irq, flags, func, param) \
101 	static Z_DECL_ALIGN(struct _isr_list) Z_GENERIC_SECTION(.intList) \
102 		__used _MK_ISR_NAME(func, __COUNTER__) = \
103 			{irq, flags, (void *)&func, (const void *)param}
104 
105 #define IRQ_TABLE_SIZE (CONFIG_NUM_IRQS - CONFIG_GEN_IRQ_START_VECTOR)
106 
107 #ifdef CONFIG_DYNAMIC_INTERRUPTS
108 void z_isr_install(unsigned int irq, void (*routine)(const void *),
109 		   const void *param);
110 
111 #ifdef CONFIG_SHARED_INTERRUPTS
112 int z_isr_uninstall(unsigned int irq, void (*routine)(const void *),
113 		    const void *param);
114 #endif /* CONFIG_SHARED_INTERRUPTS */
115 #endif
116 
117 #ifdef __cplusplus
118 }
119 #endif
120 
121 #endif /* _ASMLANGUAGE */
122 
123 #endif /* ZEPHYR_INCLUDE_SW_ISR_TABLE_H_ */
124