1 /*
2 * Copyright (c) 2006-2024, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2013-07-06 Bernard first version
9 * 2018-11-22 Jesven add smp support
10 */
11
12 #include <rthw.h>
13 #include <rtthread.h>
14 #include "interrupt.h"
15
16 #include "gicv3.h"
17
18 /* exception and interrupt handler table */
19 struct rt_irq_desc isr_table[MAX_HANDLERS];
20
21 #ifndef RT_USING_SMP
22 /* Those varibles will be accessed in ISR, so we need to share them. */
23 rt_uint32_t rt_interrupt_from_thread = 0;
24 rt_uint32_t rt_interrupt_to_thread = 0;
25 rt_uint32_t rt_thread_switch_interrupt_flag = 0;
26
27 #ifdef RT_USING_HOOK
28 static void (*rt_interrupt_switch_hook)(void);
29
rt_interrupt_switch_sethook(void (* hook)(void))30 void rt_interrupt_switch_sethook(void (*hook)(void))
31 {
32 rt_interrupt_switch_hook = hook;
33 }
34 #endif
35
rt_interrupt_hook(void)36 void rt_interrupt_hook(void)
37 {
38 RT_OBJECT_HOOK_CALL(rt_interrupt_switch_hook, ());
39 }
40 #endif
41
42 const unsigned int VECTOR_BASE = 0x00;
43 extern void rt_cpu_vector_set_base(unsigned int addr);
44 extern int system_vectors;
45
rt_hw_vector_init(void)46 void rt_hw_vector_init(void)
47 {
48 rt_cpu_vector_set_base((unsigned int)&system_vectors);
49 }
50
51 /**
52 * This function will initialize hardware interrupt
53 * Called by the primary cpu(cpu0)
54 */
rt_hw_interrupt_init(void)55 void rt_hw_interrupt_init(void)
56 {
57 rt_uint32_t gic_dist_base;
58 rt_uint32_t gic_irq_start;
59
60 /* initialize vector table */
61 /* rt_hw_vector_init(); */
62
63 /* initialize exceptions table */
64 rt_memset(isr_table, 0x00, sizeof(isr_table));
65
66 /* initialize ARM GIC */
67 gic_dist_base = platform_get_gic_dist_base();
68 gic_irq_start = GIC_IRQ_START;
69
70 arm_gic_dist_init(0, gic_dist_base, gic_irq_start);
71
72 arm_gic_cpu_init(0);
73 arm_gic_redist_init(0);
74 }
75
76 /**
77 * This function will mask a interrupt.
78 * @param vector the interrupt number
79 */
rt_hw_interrupt_mask(int vector)80 void rt_hw_interrupt_mask(int vector)
81 {
82 arm_gic_mask(0, vector);
83 }
84
85 /**
86 * This function will un-mask a interrupt.
87 * @param vector the interrupt number
88 */
rt_hw_interrupt_umask(int vector)89 void rt_hw_interrupt_umask(int vector)
90 {
91 arm_gic_umask(0, vector);
92 }
93
94 /**
95 * This function returns the active interrupt number.
96 * @param none
97 */
rt_hw_interrupt_get_irq(void)98 int rt_hw_interrupt_get_irq(void)
99 {
100 return arm_gic_get_active_irq(0);
101 }
102
103 /**
104 * This function acknowledges the interrupt.
105 * @param vector the interrupt number
106 */
rt_hw_interrupt_ack(int vector)107 void rt_hw_interrupt_ack(int vector)
108 {
109 arm_gic_ack(0, vector);
110 }
111
112 /**
113 * This function set interrupt CPU targets.
114 * @param vector: the interrupt number
115 * cpu_mask: target cpus mask, one bit for one core
116 */
rt_hw_interrupt_set_target_cpus(int vector,unsigned int cpu_mask)117 void rt_hw_interrupt_set_target_cpus(int vector, unsigned int cpu_mask)
118 {
119 arm_gic_set_cpu(0, vector, cpu_mask);
120 }
121
122 /**
123 * This function get interrupt CPU targets.
124 * @param vector: the interrupt number
125 * @return target cpus mask, one bit for one core
126 */
rt_hw_interrupt_get_target_cpus(int vector)127 unsigned int rt_hw_interrupt_get_target_cpus(int vector)
128 {
129 return arm_gic_get_target_cpu(0, vector);
130 }
131
132 /**
133 * This function set interrupt triger mode.
134 * @param vector: the interrupt number
135 * mode: interrupt triger mode; 0: level triger, 1: edge triger
136 */
rt_hw_interrupt_set_triger_mode(int vector,unsigned int mode)137 void rt_hw_interrupt_set_triger_mode(int vector, unsigned int mode)
138 {
139 arm_gic_set_configuration(0, vector, mode);
140 }
141
142 /**
143 * This function get interrupt triger mode.
144 * @param vector: the interrupt number
145 * @return interrupt triger mode; 0: level triger, 1: edge triger
146 */
rt_hw_interrupt_get_triger_mode(int vector)147 unsigned int rt_hw_interrupt_get_triger_mode(int vector)
148 {
149 return arm_gic_get_configuration(0, vector);
150 }
151
152 /**
153 * This function set interrupt pending flag.
154 * @param vector: the interrupt number
155 */
rt_hw_interrupt_set_pending(int vector)156 void rt_hw_interrupt_set_pending(int vector)
157 {
158 arm_gic_set_pending_irq(0, vector);
159 }
160
161 /**
162 * This function get interrupt pending flag.
163 * @param vector: the interrupt number
164 * @return interrupt pending flag, 0: not pending; 1: pending
165 */
rt_hw_interrupt_get_pending(int vector)166 unsigned int rt_hw_interrupt_get_pending(int vector)
167 {
168 return arm_gic_get_pending_irq(0, vector);
169 }
170
171 /**
172 * This function clear interrupt pending flag.
173 * @param vector: the interrupt number
174 */
rt_hw_interrupt_clear_pending(int vector)175 void rt_hw_interrupt_clear_pending(int vector)
176 {
177 arm_gic_clear_pending_irq(0, vector);
178 }
179
180 /**
181 * This function set interrupt priority value.
182 * @param vector: the interrupt number
183 * priority: the priority of interrupt to set
184 */
rt_hw_interrupt_set_priority(int vector,unsigned int priority)185 void rt_hw_interrupt_set_priority(int vector, unsigned int priority)
186 {
187 arm_gic_set_priority(0, vector, priority);
188 }
189
190 /**
191 * This function get interrupt priority.
192 * @param vector: the interrupt number
193 * @return interrupt priority value
194 */
rt_hw_interrupt_get_priority(int vector)195 unsigned int rt_hw_interrupt_get_priority(int vector)
196 {
197 return arm_gic_get_priority(0, vector);
198 }
199
200 /**
201 * This function set priority masking threshold.
202 * @param priority: priority masking threshold
203 */
rt_hw_interrupt_set_priority_mask(unsigned int priority)204 void rt_hw_interrupt_set_priority_mask(unsigned int priority)
205 {
206 arm_gic_set_interface_prior_mask(0, priority);
207 }
208
209 /**
210 * This function get priority masking threshold.
211 * @param none
212 * @return priority masking threshold
213 */
rt_hw_interrupt_get_priority_mask(void)214 unsigned int rt_hw_interrupt_get_priority_mask(void)
215 {
216 return arm_gic_get_interface_prior_mask(0);
217 }
218
219 /**
220 * This function set priority grouping field split point.
221 * @param bits: priority grouping field split point
222 * @return 0: success; -1: failed
223 */
rt_hw_interrupt_set_prior_group_bits(unsigned int bits)224 int rt_hw_interrupt_set_prior_group_bits(unsigned int bits)
225 {
226 int status;
227
228 if (bits < 8)
229 {
230 arm_gic_set_binary_point(0, (7 - bits));
231 status = 0;
232 }
233 else
234 {
235 status = -1;
236 }
237
238 return (status);
239 }
240
241 /**
242 * This function get priority grouping field split point.
243 * @param none
244 * @return priority grouping field split point
245 */
rt_hw_interrupt_get_prior_group_bits(void)246 unsigned int rt_hw_interrupt_get_prior_group_bits(void)
247 {
248 unsigned int bp;
249
250 bp = arm_gic_get_binary_point(0) & 0x07;
251
252 return (7 - bp);
253 }
254
255 /**
256 * This function will install a interrupt service routine to a interrupt.
257 * @param vector the interrupt number
258 * @param new_handler the interrupt service routine to be installed
259 * @param old_handler the old interrupt service routine
260 */
rt_hw_interrupt_install(int vector,rt_isr_handler_t handler,void * param,const char * name)261 rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
262 void *param, const char *name)
263 {
264 rt_isr_handler_t old_handler = RT_NULL;
265
266 if (vector < MAX_HANDLERS)
267 {
268 old_handler = isr_table[vector].handler;
269
270 if (handler != RT_NULL)
271 {
272 #ifdef RT_USING_INTERRUPT_INFO
273 rt_strncpy(isr_table[vector].name, name, RT_NAME_MAX);
274 #endif /* RT_USING_INTERRUPT_INFO */
275 isr_table[vector].handler = handler;
276 isr_table[vector].param = param;
277 }
278 }
279
280 return old_handler;
281 }
282
283