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-02-08 RT-Thread the first version
9 * 2020-03-02 Howard Su Use structure to access registers
10 */
11
12 #include <rthw.h>
13 #include <rtthread.h>
14
15 #include "interrupt.h"
16
17 extern rt_atomic_t rt_interrupt_nest;
18 rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread;
19 rt_uint32_t rt_thread_switch_interrupt_flag;
20
21 static struct rt_irq_desc isr_table[INTERRUPTS_MAX];
22
rt_hw_interrupt_handler(int vector,void * param)23 static void rt_hw_interrupt_handler(int vector, void *param)
24 {
25 rt_kprintf("Unhandled interrupt %d occured!!!\n", vector);
26 }
27
28 /**
29 * This function will initialize hardware interrupt
30 */
rt_hw_interrupt_init(void)31 void rt_hw_interrupt_init(void)
32 {
33 rt_int32_t idx;
34
35 rt_memset(isr_table, 0x00, sizeof(isr_table));
36 for (idx = 0; idx < INTERRUPTS_MAX; idx ++)
37 {
38 isr_table[idx].handler = rt_hw_interrupt_handler;
39 }
40
41 /* init interrupt nest, and context in thread sp */
42 rt_interrupt_nest = 0;
43 rt_interrupt_from_thread = 0;
44 rt_interrupt_to_thread = 0;
45 rt_thread_switch_interrupt_flag = 0;
46
47 /* set base_addr reg */
48 INTC->base_addr_reg = 0x00000000;
49 /* clear enable */
50 INTC->en_reg[0] = 0x00000000;
51 INTC->en_reg[1] = 0x00000000;
52 /* mask interrupt */
53 INTC->mask_reg[0] = 0xFFFFFFFF;
54 INTC->mask_reg[1] = 0xFFFFFFFF;
55 /* clear pending */
56 INTC->pend_reg[0] = 0x00000000;
57 INTC->pend_reg[1] = 0x00000000;
58 /* set priority */
59 INTC->resp_reg[0] = 0x00000000;
60 INTC->resp_reg[1] = 0x00000000;
61 /* close fiq interrupt */
62 INTC->ff_reg[0] = 0x00000000;
63 INTC->ff_reg[1] = 0x00000000;
64 }
65
66 /**
67 * This function will mask a interrupt.
68 * @param vector the interrupt number
69 */
rt_hw_interrupt_mask(int vector)70 void rt_hw_interrupt_mask(int vector)
71 {
72 int index;
73 if ((vector < 0) || (vector >= INTERRUPTS_MAX))
74 {
75 return;
76 }
77
78 index = (vector & 0xE0) != 0;
79 vector = (vector & 0x1F);
80
81 INTC->mask_reg[index] |= 1 << vector;
82 }
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 int index;
92 if ((vector < 0) || (vector >= INTERRUPTS_MAX))
93 {
94 return;
95 }
96
97 index = (vector & 0xE0) != 0;
98 vector = (vector & 0x1F);
99
100 INTC->mask_reg[index] &= ~(1 << vector);
101 }
102
103 /**
104 * This function will install a interrupt service routine to a interrupt.
105 * @param vector the interrupt number
106 * @param handler the interrupt service routine to be installed
107 * @param param the interrupt service function parameter
108 * @param name the interrupt name
109 * @return old handler
110 */
rt_hw_interrupt_install(int vector,rt_isr_handler_t handler,void * param,const char * name)111 rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
112 void *param, const char *name)
113 {
114 rt_isr_handler_t old_handler = RT_NULL;
115 int index;
116
117 if ((vector < 0) || (vector >= INTERRUPTS_MAX))
118 {
119 return old_handler;
120 }
121
122 old_handler = isr_table[vector].handler;
123
124 #ifdef RT_USING_INTERRUPT_INFO
125 rt_strncpy(isr_table[vector].name, name, RT_NAME_MAX);
126 #endif /* RT_USING_INTERRUPT_INFO */
127 isr_table[vector].handler = handler;
128 isr_table[vector].param = param;
129
130 index = (vector & 0xE0) != 0;
131 vector = (vector & 0x1F);
132
133 INTC->pend_reg[index] &= ~(0x1 << vector);
134 INTC->en_reg[index] |= 0x1 << vector;
135
136 return old_handler;
137 }
138
rt_interrupt_dispatch(rt_uint32_t fiq_irq)139 void rt_interrupt_dispatch(rt_uint32_t fiq_irq)
140 {
141 void *param;
142 int vector;
143 rt_isr_handler_t isr_func;
144 int index;
145
146 vector = INTC->vector_reg - INTC->base_addr_reg;
147 vector = vector >> 2;
148
149 isr_func = isr_table[vector].handler;
150 param = isr_table[vector].param;
151
152 /* jump to fun */
153 isr_func(vector, param);
154 /* clear pend bit */
155
156 index = (vector & 0xE0) != 0;
157 vector = (vector & 0x1F);
158
159 INTC->pend_reg[index] &= ~(0x1 << vector);
160
161 #ifdef RT_USING_INTERRUPT_INFO
162 isr_table[vector].counter ++;
163 #endif
164 }
165
166
167
168
169
170
171
172
173
174