1 /*
2 * Copyright (c) 2006-2021, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2018/5/3 Bernard first version
9 * 2019-07-28 zdzn add smp support
10 * 2019-08-09 zhangjun fixup the problem of smp startup and scheduling issues,
11 * write addr to mailbox3 to startup smp, and we use mailbox0 for ipi
12 */
13
14 #include <rthw.h>
15 #include <rtthread.h>
16
17 #include "cp15.h"
18 #include <board.h>
19
20 #define MAX_HANDLERS 72
21
22 #ifdef RT_USING_SMP
23 #define rt_interrupt_nest rt_cpu_self()->irq_nest
24 #else
25 extern volatile rt_atomic_t rt_interrupt_nest;
26 #endif
27
28 const unsigned int VECTOR_BASE = 0x00;
29 extern void rt_cpu_vector_set_base(unsigned int addr);
30 extern int system_vectors;
31
rt_hw_vector_init(void)32 void rt_hw_vector_init(void)
33 {
34 rt_cpu_vector_set_base((unsigned int)&system_vectors);
35 }
36
37 /* exception and interrupt handler table */
38 struct rt_irq_desc isr_table[MAX_HANDLERS];
39
40 rt_uint32_t rt_interrupt_from_thread;
41 rt_uint32_t rt_interrupt_to_thread;
42 rt_uint32_t rt_thread_switch_interrupt_flag;
43
44 extern int system_vectors;
45
default_isr_handler(int vector,void * param)46 static void default_isr_handler(int vector, void *param)
47 {
48 #ifdef RT_USING_SMP
49 rt_kprintf("cpu %d unhandled irq: %d\n", rt_hw_cpu_id(),vector);
50 #else
51 rt_kprintf("unhandled irq: %d\n",vector);
52 #endif
53 }
54
55 /**
56 * This function will initialize hardware interrupt
57 */
rt_hw_interrupt_init(void)58 void rt_hw_interrupt_init(void)
59 {
60 rt_uint32_t index;
61
62 /* mask all of interrupts */
63 IRQ_DISABLE_BASIC = 0x000000ff;
64 IRQ_DISABLE1 = 0xffffffff;
65 IRQ_DISABLE2 = 0xffffffff;
66 for (index = 0; index < MAX_HANDLERS; index ++)
67 {
68 isr_table[index].handler = default_isr_handler;
69 isr_table[index].param = RT_NULL;
70 #ifdef RT_USING_INTERRUPT_INFO
71 rt_strncpy(isr_table[index].name, "unknown", RT_NAME_MAX);
72 isr_table[index].counter = 0;
73 #endif
74 }
75
76 /* init interrupt nest, and context in thread sp */
77 rt_interrupt_nest = 0;
78 rt_interrupt_from_thread = 0;
79 rt_interrupt_to_thread = 0;
80 rt_thread_switch_interrupt_flag = 0;
81 }
82
83 /**
84 * This function will mask a interrupt.
85 * @param vector the interrupt number
86 */
rt_hw_interrupt_mask(int vector)87 void rt_hw_interrupt_mask(int vector)
88 {
89
90 if (vector < 32)
91 {
92 IRQ_DISABLE1 = (1 << vector);
93 }
94 else if (vector < 64)
95 {
96 vector = vector % 32;
97 IRQ_DISABLE2 = (1 << vector);
98 }
99 else
100 {
101 vector = vector - 64;
102 IRQ_DISABLE_BASIC = (1 << vector);
103 }
104 }
105
106 /**
107 * This function will un-mask a interrupt.
108 * @param vector the interrupt number
109 */
rt_hw_interrupt_umask(int vector)110 void rt_hw_interrupt_umask(int vector)
111 {
112 if (vector < 32)
113 {
114 IRQ_ENABLE1 = (1 << vector);
115 }
116 else if (vector < 64)
117 {
118 vector = vector % 32;
119 IRQ_ENABLE2 = (1 << vector);
120 }
121 else
122 {
123 vector = vector - 64;
124 IRQ_ENABLE_BASIC = (1 << vector);
125 }
126 }
127
128 /**
129 * This function will install a interrupt service routine to a interrupt.
130 * @param vector the interrupt number
131 * @param new_handler the interrupt service routine to be installed
132 * @param old_handler the old interrupt service routine
133 */
rt_hw_interrupt_install(int vector,rt_isr_handler_t handler,void * param,const char * name)134 rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
135 void *param, const char *name)
136 {
137 rt_isr_handler_t old_handler = RT_NULL;
138
139 if (vector < MAX_HANDLERS)
140 {
141 old_handler = isr_table[vector].handler;
142
143 if (handler != RT_NULL)
144 {
145 #ifdef RT_USING_INTERRUPT_INFO
146 rt_strncpy(isr_table[vector].name, name, RT_NAME_MAX);
147 #endif /* RT_USING_INTERRUPT_INFO */
148 isr_table[vector].handler = handler;
149 isr_table[vector].param = param;
150 }
151 }
152
153 return old_handler;
154 }
155
156 #ifdef RT_USING_SMP
rt_hw_ipi_send(int ipi_vector,unsigned int cpu_mask)157 void rt_hw_ipi_send(int ipi_vector, unsigned int cpu_mask)
158 {
159 __DSB();
160 if (cpu_mask & 0x1)
161 {
162 send_ipi_msg(0, ipi_vector);
163 }
164 if (cpu_mask & 0x2)
165 {
166 send_ipi_msg(1, ipi_vector);
167 }
168 if (cpu_mask & 0x4)
169 {
170 send_ipi_msg(2, ipi_vector);
171 }
172 if (cpu_mask & 0x8)
173 {
174 send_ipi_msg(3, ipi_vector);
175 }
176 __DSB();
177 }
178 #endif
179
180 #ifdef RT_USING_SMP
rt_hw_ipi_handler_install(int ipi_vector,rt_isr_handler_t ipi_isr_handler)181 void rt_hw_ipi_handler_install(int ipi_vector, rt_isr_handler_t ipi_isr_handler)
182 {
183 /* note: ipi_vector maybe different with irq_vector */
184 rt_hw_interrupt_install(ipi_vector, ipi_isr_handler, 0, "IPI_HANDLER");
185 }
186 #endif
187